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,
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,
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;
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);
}
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
}
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;
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);
}
&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) {
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;
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);
}
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;
}
/* 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;
}
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) {
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 */
io_context->initialized = 0;
io_context->identity = NULL;
io_context->prompt_count = 0;
+ io_context->password_to_save = NULL;
}
return check_error (err);
}
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);
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) {
} else {
err = check_error (KIM_NO_UI_ERR);
}
+
+ kim_string_free (&io_context->password_to_save);
}
return check_error (err);
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;
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); }
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,
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,
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;
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);
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,
void *tcontext;
kim_identity identity;
kim_count prompt_count;
+ kim_string password_to_save;
} kim_ui_context;
/* ------------------------------------------------------------------------ */
+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)
{
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);
}
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);
}
/* ------------------------------------------------------------------------ */
-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;
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);
}
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);