From ef05efb0c1cfb734437b55ec5f8390c2fb19a5ed Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Tue, 23 Sep 2008 21:46:12 +0000 Subject: [PATCH] Renamed error handling files to reflect what they do now. Moved GUI code into OS-specific directory. Fixed bugs in cache collection iterator routines where it was mishandling the magic empty ccache created when the cache collection is empty. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20747 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/kim/kim.h | 2 +- src/include/kim/kim_credential.h | 15 +- src/include/kim/kim_error.h | 100 ------- src/include/kim/kim_string.h | 37 +++ src/include/kim/kim_types.h | 2 + src/kim/lib/kim-lite.exports | 4 +- src/kim/lib/kim.exports | 4 +- src/kim/lib/kim_ccache.c | 45 ++- src/kim/lib/kim_credential.c | 32 +- .../lib/{kim_error.c => kim_error_message.c} | 10 - .../lib/{kim_error_code.et => kim_errors.et} | 0 src/kim/lib/kim_string.c | 8 + src/kim/lib/kim_ui.c | 274 +++++++++--------- src/kim/lib/kim_ui_gui_private.h | 56 ++-- src/kim/lib/kim_ui_private.h | 20 +- .../lib/{kim_ui_gui.c => mac/kim_os_ui_gui.c} | 68 ++--- 16 files changed, 328 insertions(+), 349 deletions(-) delete mode 100644 src/include/kim/kim_error.h rename src/kim/lib/{kim_error.c => kim_error_message.c} (95%) rename src/kim/lib/{kim_error_code.et => kim_errors.et} (100%) rename src/kim/lib/{kim_ui_gui.c => mac/kim_os_ui_gui.c} (68%) diff --git a/src/include/kim/kim.h b/src/include/kim/kim.h index 893891def..19e82ecb6 100644 --- a/src/include/kim/kim.h +++ b/src/include/kim/kim.h @@ -30,8 +30,8 @@ extern "C" { #endif #include +#include #include -#include #include #include #include diff --git a/src/include/kim/kim_credential.h b/src/include/kim/kim_credential.h index 88ccc5dce..c25b02e90 100644 --- a/src/include/kim/kim_credential.h +++ b/src/include/kim/kim_credential.h @@ -451,7 +451,8 @@ kim_error kim_credential_get_expiration_time (kim_credential in_credential, /*! * \param in_credential a credential object. * \param out_renewal_expiration_time on exit, the time when \a in_credential will no longer - * be renewable. May be in the past or future. + * be renewable. May be in the past or future. If + * credentials are not renewable at all, returns 0. * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. * \brief Get the time when the credentials will no longer be renewable. * \sa kim_ccache_get_renewal_expiration_time @@ -459,7 +460,17 @@ kim_error kim_credential_get_expiration_time (kim_credential in_credential, kim_error kim_credential_get_renewal_expiration_time (kim_credential in_credential, kim_time *out_renewal_expiration_time); +/*! + * \param in_credential a credential object. + * \param out_ticket_flags on exit, the krb5 ticket flags for \a in_credential. + * See krb5 API documentation for the meaning of these flags. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the krb5 ticket_flags for a credential. + */ +kim_error kim_credential_get_krb5_ticket_flags (kim_credential in_credential, + krb5_flags *out_ticket_flags); + /*! * \param in_credential a credential object. * \param in_client_identity a client identity. @@ -521,7 +532,7 @@ kim_error kim_credential_validate (kim_credential *io_credential, /*! * \param in_credential a credential object containing a change * password credential. Use - * #kim_credential_change_password to obtain + * #kim_credential_create_for_change_password to obtain * a change password credential. * \param in_identity an identity to change the password for. May * be different than the identity the credential diff --git a/src/include/kim/kim_error.h b/src/include/kim/kim_error.h deleted file mode 100644 index 07c6d172f..000000000 --- a/src/include/kim/kim_error.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2005-2006 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#ifndef KIM_ERROR_H -#define KIM_ERROR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/*! - * \ingroup kim_types_reference - * The kim_error_t returned when no error occurred. - */ -#define KIM_NO_ERROR ((kim_error) 0) - -/*! - * \page kim_error_overview KIM Error Overview - * - * Like most C APIs, the KIM API returns numeric error codes. These error - * codes may come from KIM, krb5 or GSS APIs. In most cases the caller will - * want to handle these error programmatically. However, in some circumstances - * the caller may wish to print an error string to the user. - * - * One problem with just printing the error code to the user is that frequently - * the context behind the error has been lost. For example if KIM is trying to - * obtain credentials via referrals, it may fail partway through the process. - * In this case the error code will be KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, which - * maps to "Client not found in Kerberos database". Unfortunately this error - * isn't terribly helpful because it doesn't tell the user whether they typoed - * their principal name or if referrals failed. - * - * To avoid this problem, KIM maintains an explanatory string for the last - * error seen in each thread calling into KIM. If a caller wishes to display - * an error to the user, immediately after getting the error the caller should - * call #kim_string_get_last_error_message() to obtain a copy of the - * descriptive error message. - * - * Note that because this string is stored in thread-specific data, callers - * must call #kim_string_get_last_error_message() before calling any KIM APIs - * or any other APIs which might call into KIM. Callers who are not going - * to display this error string immediately should also make a copy of it - * so that it is not overwritten by the next call into KIM. - * - * See \ref kim_error_reference for information on specific APIs. - */ - -/*! - * \defgroup kim_error_reference KIM Error Reference Documentation - * @{ - */ - -/*! - * \param out_string On success, a human-readable UTF-8 string describing the - * error representedby \a in_error. Must be freed with - * kim_string_free(). - * \param in_error an error code. Used to verify that the correct error - * string will be returned (see note below). - * \return On success, KIM_NO_ERROR. - * \note This API is implemented using thread local storage. It should be - * called immediately after a KIM API returns an error code so that the correct - * string is returned. The returned copy may then be held by the caller until - * needed. If \a in_error does not match the last saved error KIM may return - * a less descriptive string. - * \brief Get a text description of an error suitable for display to the user. - */ -kim_error kim_string_get_last_error_message (kim_string *out_string, - kim_error in_error); - -/*!@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* KIM_ERROR_H */ diff --git a/src/include/kim/kim_string.h b/src/include/kim/kim_string.h index 79cd0ee24..bc4f647e8 100644 --- a/src/include/kim/kim_string.h +++ b/src/include/kim/kim_string.h @@ -39,6 +39,27 @@ extern "C" { * Memory management routines are provided for runtime consistency on * operating systems with shared libraries and multiple runtimes. * + * \section kim_string_error_messages KIM Error Messages + * + * Like most C APIs, the KIM API returns numeric error codes. These error + * codes may come from KIM, krb5 or GSS APIs. In most cases the caller will + * want to handle these error programmatically. However, in some circumstances + * the caller may wish to print an error string to the user. + * + * One problem with just printing the error code to the user is that frequently + * the context behind the error has been lost. For example if KIM is trying to + * obtain credentials via referrals, it may fail partway through the process. + * In this case the error code will be KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, which + * maps to "Client not found in Kerberos database". Unfortunately this error + * isn't terribly helpful because it doesn't tell the user whether they typoed + * their principal name or if referrals failed. + * + * To avoid this problem, KIM maintains an explanatory string for the last + * error seen in each thread calling into KIM. If a caller wishes to display + * an error to the user, immediately after getting the error the caller should + * call #kim_string_create_for_error() to obtain a copy of the + * descriptive error message. + * * See \ref kim_string_reference for information on specific APIs. */ @@ -60,6 +81,22 @@ extern "C" { kim_error kim_string_create_for_error (kim_string *out_string, kim_error in_error); +/*! + * \param out_string On success, a human-readable UTF-8 string describing the + * error representedby \a in_error. Must be freed with + * kim_string_free(). + * \param in_error an error code. Used to verify that the correct error + * string will be returned (see note below). + * \return On success, KIM_NO_ERROR. + * \note This API is implemented using thread local storage. It should be + * called immediately after a KIM API returns an error code so that the correct + * string is returned. The returned copy may then be held by the caller until + * needed. If \a in_error does not match the last saved error KIM may return + * a less descriptive string. + * \brief Get a text description of an error suitable for display to the user. + */ +kim_error kim_string_create_for_last_error (kim_string *out_string, + kim_error in_error); /*! * \param out_string on exit, a new string object which is a copy of \a in_string. diff --git a/src/include/kim/kim_types.h b/src/include/kim/kim_types.h index 545d7479c..8cf97246e 100644 --- a/src/include/kim/kim_types.h +++ b/src/include/kim/kim_types.h @@ -41,6 +41,8 @@ extern "C" { */ typedef int32_t kim_error; +#define KIM_NO_ERROR ((kim_error) 0) + /*! * A time value represented in seconds since January 1, 1970. */ diff --git a/src/kim/lib/kim-lite.exports b/src/kim/lib/kim-lite.exports index 1b8466a56..708d2753c 100644 --- a/src/kim/lib/kim-lite.exports +++ b/src/kim/lib/kim-lite.exports @@ -1,5 +1,4 @@ -kim_string_get_last_error_message - +kim_string_create_for_last_error kim_string_copy kim_string_compare kim_string_free @@ -91,6 +90,7 @@ kim_credential_get_state kim_credential_get_start_time kim_credential_get_expiration_time kim_credential_get_renewal_expiration_time +kim_credential_get_krb5_ticket_flags kim_credential_store kim_credential_renew kim_credential_validate diff --git a/src/kim/lib/kim.exports b/src/kim/lib/kim.exports index d2f2e27e7..bdacd6299 100644 --- a/src/kim/lib/kim.exports +++ b/src/kim/lib/kim.exports @@ -1,5 +1,4 @@ -kim_string_get_last_error_message - +kim_string_create_for_last_error kim_string_copy kim_string_compare kim_string_free @@ -92,6 +91,7 @@ kim_credential_get_state kim_credential_get_start_time kim_credential_get_expiration_time kim_credential_get_renewal_expiration_time +kim_credential_get_krb5_ticket_flags kim_credential_store kim_credential_verify kim_credential_renew diff --git a/src/kim/lib/kim_ccache.c b/src/kim/lib/kim_ccache.c index dd6bdf77d..713a15bf4 100644 --- a/src/kim/lib/kim_ccache.c +++ b/src/kim/lib/kim_ccache.c @@ -29,9 +29,10 @@ struct kim_ccache_iterator_opaque { krb5_context context; krb5_cccol_cursor cursor; + kim_boolean first; }; -struct kim_ccache_iterator_opaque kim_ccache_iterator_initializer = { NULL, NULL }; +struct kim_ccache_iterator_opaque kim_ccache_iterator_initializer = { NULL, NULL, 1 }; /* ------------------------------------------------------------------------ */ @@ -83,9 +84,34 @@ kim_error kim_ccache_iterator_next (kim_ccache_iterator in_ccache_iterator, if (!err && !out_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - krb5_error_code terr = krb5_cccol_cursor_next (in_ccache_iterator->context, - in_ccache_iterator->cursor, - &ccache); + err = krb5_cccol_cursor_next (in_ccache_iterator->context, + in_ccache_iterator->cursor, + &ccache); + if (err == KRB5_CC_END) { + ccache = NULL; /* out of ccaches */ + err = KIM_NO_ERROR; + } + } + + if (!err && ccache && in_ccache_iterator->first) { + krb5_principal principal = NULL; + + /* krb5 API is sneaky and returns a single empty ccache if the + * cache collection is empty. Check for it: */ + err = krb5_error (in_ccache_iterator->context, + krb5_cc_get_principal (in_ccache_iterator->context, + ccache, + &principal)); + + if (err) { + krb5_cc_close (in_ccache_iterator->context, ccache); + ccache = NULL; + err = KIM_NO_ERROR; + } + } + + if (!err) { + in_ccache_iterator->first = 0; if (ccache) { err = kim_ccache_create_from_krb5_ccache (out_ccache, @@ -93,10 +119,7 @@ kim_error kim_ccache_iterator_next (kim_ccache_iterator in_ccache_iterator, ccache); } else { *out_ccache = NULL; /* no more ccaches */ - } - if (terr && terr != KRB5_CC_END) { - err = krb5_error (in_ccache_iterator->context, terr); - } + } } if (ccache) { krb5_cc_close (in_ccache_iterator->context, ccache); } @@ -275,6 +298,7 @@ kim_error kim_ccache_create_from_client_identity (kim_ccache *out_ccache, while (!err && !found) { kim_ccache ccache = NULL; kim_identity identity = NULL; + kim_comparison comparison; err = kim_ccache_iterator_next (iterator, &ccache); @@ -296,10 +320,11 @@ kim_error kim_ccache_create_from_client_identity (kim_ccache *out_ccache, } if (!err) { - err = kim_identity_compare (in_client_identity, identity, &found); + err = kim_identity_compare (in_client_identity, identity, &comparison); } - if (!err && found) { + if (!err && kim_comparison_is_equal_to (comparison)) { + found = 1; *out_ccache = ccache; ccache = NULL; } diff --git a/src/kim/lib/kim_credential.c b/src/kim/lib/kim_credential.c index f81b50f12..36c6ca1b6 100644 --- a/src/kim/lib/kim_credential.c +++ b/src/kim/lib/kim_credential.c @@ -281,12 +281,13 @@ kim_error kim_credential_create_new (kim_credential *out_credential, kim_options_free_init_cred_options (credential->context, &init_cred_options); } + if (credential && principal) { krb5_free_principal (credential->context, principal); } + if (!err) { *out_credential = credential; credential = NULL; } - if (principal ) { krb5_free_principal (credential->context, principal); } if (!in_options) { kim_options_free (&options); } kim_string_free (&service); kim_credential_free (&credential); @@ -781,7 +782,8 @@ kim_error kim_credential_get_start_time (kim_credential in_credential, { kim_error err = KIM_NO_ERROR; - if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_start_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { *out_start_time = (in_credential->creds->times.starttime ? @@ -815,10 +817,32 @@ kim_error kim_credential_get_renewal_expiration_time (kim_credential in_credent { kim_error err = KIM_NO_ERROR; - if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_renewal_expiration_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_credential->creds->ticket_flags & TKT_FLG_RENEWABLE) { + *out_renewal_expiration_time = in_credential->creds->times.renew_till; + } else { + *out_renewal_expiration_time = 0; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_krb5_ticket_flags (kim_credential in_credential, + krb5_flags *out_ticket_flags) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_ticket_flags) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - *out_renewal_expiration_time = in_credential->creds->times.renew_till; + *out_ticket_flags = in_credential->creds->ticket_flags; } return check_error (err); diff --git a/src/kim/lib/kim_error.c b/src/kim/lib/kim_error_message.c similarity index 95% rename from src/kim/lib/kim_error.c rename to src/kim/lib/kim_error_message.c index c481e2fb2..b292505c4 100644 --- a/src/kim/lib/kim_error.c +++ b/src/kim/lib/kim_error_message.c @@ -211,13 +211,3 @@ void kim_error_terminate (void) k5_mutex_destroy (&kim_error_lock); } -#pragma mark -- Public API -- - - -/* ------------------------------------------------------------------------ */ - -kim_error kim_string_get_last_error_message (kim_string *out_string, - kim_error in_error) -{ - return kim_string_copy (out_string, kim_error_message (in_error)); -} diff --git a/src/kim/lib/kim_error_code.et b/src/kim/lib/kim_errors.et similarity index 100% rename from src/kim/lib/kim_error_code.et rename to src/kim/lib/kim_errors.et diff --git a/src/kim/lib/kim_string.c b/src/kim/lib/kim_string.c index 6968f19d9..2dc284c93 100644 --- a/src/kim/lib/kim_string.c +++ b/src/kim/lib/kim_string.c @@ -114,6 +114,14 @@ kim_error kim_string_create_from_buffer (kim_string *out_string, /* ------------------------------------------------------------------------ */ +kim_error kim_string_create_for_last_error (kim_string *out_string, + kim_error in_error) +{ + return kim_string_copy (out_string, kim_error_message (in_error)); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_string_copy (kim_string *out_string, kim_string in_string) { diff --git a/src/kim/lib/kim_ui.c b/src/kim/lib/kim_ui.c index 36920144e..a87e150ba 100644 --- a/src/kim/lib/kim_ui.c +++ b/src/kim/lib/kim_ui.c @@ -31,71 +31,15 @@ static kim_prompt_type kim_ui_ptype2ktype (krb5_prompt_type type) { - switch (type) { - case KRB5_PROMPT_TYPE_PASSWORD: - return kim_prompt_type_password; - - case KRB5_PROMPT_TYPE_PREAUTH: - return kim_prompt_type_preauth; + if (type == KRB5_PROMPT_TYPE_PASSWORD) { + return kim_prompt_type_password; + + } else if (type == KRB5_PROMPT_TYPE_PREAUTH) { + return kim_prompt_type_preauth; } return kim_prompt_type_preauth; } -/* ------------------------------------------------------------------------ */ -/* Set the identity field in your context and pass the context as the data */ - -krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, - void *in_context, - const char *in_name, - const char *in_banner, - int in_num_prompts, - krb5_prompt in_prompts[]) -{ - kim_error err = KIM_NO_ERROR; - krb5_prompt_type *types = NULL; - kim_ui_context *context = (kim_ui_context *) in_context; - int i; - - if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_prompts ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - types = krb5_get_prompt_types (in_krb5_context); - if (!types) { err = check_error (KIM_NULL_PARAMETER_ERR); } - } - - for (i = 0; !err && i < in_num_prompts; i++) { - char *reply = NULL; - - err = kim_ui_auth_prompt (context, - context->identity, - kim_ui_ptype2ktype (types[i]), - in_prompts[i].hidden, - in_name, - in_banner, - in_prompts[i].prompt, - &reply); - - if (!err) { - uint32_t reply_len = strlen (reply); - - if ((reply_len + 1) > in_prompts[i].reply->length) { - kim_debug_printf ("%s(): reply %d is too long (is %d, should be %d)\n", - __FUNCTION__, i, - reply_len, in_prompts[i].reply->length); - reply_len = in_prompts[i].reply->length; - } - - memmove (in_prompts[i].reply->data, reply, reply_len + 1); - in_prompts[i].reply->length = reply_len; - } - - kim_ui_free_string (context, &reply); - } - - return check_error (err); -} #pragma mark - @@ -110,7 +54,7 @@ kim_error kim_ui_init (kim_ui_context *io_context) if (!err) { #ifndef LEAN_CLIENT kim_ui_environment environment = kim_library_ui_environment (); - + if (environment == KIM_UI_ENVIRONMENT_GUI) { #endif /* LEAN_CLIENT */ io_context->type = kim_ui_type_gui_plugin; @@ -120,9 +64,9 @@ kim_error kim_ui_init (kim_ui_context *io_context) if (err) { io_context->type = kim_ui_type_gui_builtin; - err = kim_ui_gui_init ((kim_ui_gui_context *) &io_context->tcontext); + err = kim_os_ui_gui_init ((kim_ui_gui_context *) &io_context->tcontext); } - + } else if (environment == KIM_UI_ENVIRONMENT_CLI) { io_context->type = kim_ui_type_cli; @@ -134,7 +78,11 @@ kim_error kim_ui_init (kim_ui_context *io_context) err = check_error (KIM_NO_UI_ERR); } #endif /* LEAN_CLIENT */ - } + } + + if (!err) { + io_context->identity = NULL; + } return check_error (err); } @@ -156,8 +104,8 @@ kim_error kim_ui_enter_identity (kim_ui_context *in_context, #ifndef LEAN_CLIENT } else if (in_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_enter_identity ((kim_ui_gui_context) in_context->tcontext, - out_identity); + err = kim_os_ui_gui_enter_identity ((kim_ui_gui_context) in_context->tcontext, + out_identity); } else if (in_context->type == kim_ui_type_cli) { err = kim_ui_cli_enter_identity ((kim_ui_cli_context) in_context->tcontext, @@ -193,9 +141,9 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, #ifndef LEAN_CLIENT } else if (in_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_select_identity ((kim_ui_gui_context) in_context->tcontext, - in_hints, - out_identity); + err = kim_os_ui_gui_select_identity ((kim_ui_gui_context) in_context->tcontext, + in_hints, + out_identity); } else if (in_context->type == kim_ui_type_cli) { err = kim_ui_cli_select_identity ((kim_ui_cli_context) in_context->tcontext, @@ -213,58 +161,103 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, } /* ------------------------------------------------------------------------ */ +/* Set the identity field in your context and pass the context as the data */ -kim_error kim_ui_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) +krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, + void *in_context, + const char *in_name, + const char *in_banner, + int in_num_prompts, + krb5_prompt in_prompts[]) { kim_error err = KIM_NO_ERROR; + krb5_prompt_type *types = NULL; + kim_ui_context *context = (kim_ui_context *) in_context; + int i; - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - /* in_title, in_message or in_description may be NULL */ + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_prompts ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - if (in_context->type == kim_ui_type_gui_plugin) { - err = kim_ui_plugin_auth_prompt ((kim_ui_plugin_context) in_context->tcontext, - in_identity, - in_type, - in_hide_reply, - in_title, - in_message, - in_description, - out_reply); - -#ifndef LEAN_CLIENT - } else if (in_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_auth_prompt ((kim_ui_gui_context) in_context->tcontext, - in_identity, - in_type, - in_hide_reply, - in_title, - in_message, - in_description, - out_reply); + types = krb5_get_prompt_types (in_krb5_context); + if (!types) { err = check_error (KIM_NULL_PARAMETER_ERR); } + } + + for (i = 0; !err && i < in_num_prompts; i++) { + char *reply = NULL; + kim_prompt_type type = kim_ui_ptype2ktype (types[i]); + kim_boolean got_saved_password = 0; + + if (type == kim_prompt_type_password) { + /* Check for saved password on OSes that support it */ + kim_error terr = KIM_NO_ERROR; - } else if (in_context->type == kim_ui_type_cli) { - err = kim_ui_cli_auth_prompt ((kim_ui_cli_context) in_context->tcontext, - in_identity, - in_type, - in_hide_reply, - in_title, - in_message, - in_description, - out_reply); + terr = kim_os_identity_get_saved_password (context->identity, + (kim_string *) &reply); + if (!terr) { got_saved_password = 1; } + } + + if (!got_saved_password) { + if (context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_auth_prompt ((kim_ui_plugin_context) context->tcontext, + context->identity, + type, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply); + +#ifndef LEAN_CLIENT + } else if (context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_auth_prompt ((kim_ui_gui_context) context->tcontext, + context->identity, + type, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply); + + } else if (context->type == kim_ui_type_cli) { + err = kim_ui_cli_auth_prompt ((kim_ui_cli_context) context->tcontext, + context->identity, + type, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply); #endif /* LEAN_CLIENT */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + if (!err) { + uint32_t reply_len = strlen (reply); - } else { - err = check_error (KIM_NO_UI_ERR); + if ((reply_len + 1) > in_prompts[i].reply->length) { + kim_debug_printf ("%s(): reply %d is too long (is %d, should be %d)\n", + __FUNCTION__, i, + reply_len, in_prompts[i].reply->length); + reply_len = in_prompts[i].reply->length; + } + + memmove (in_prompts[i].reply->data, reply, reply_len + 1); + in_prompts[i].reply->length = reply_len; + } + + /* Clean up reply buffer. Saved passwords are allocated by KIM. */ + if (reply) { + memset (reply, '\0', strlen (reply)); + if (got_saved_password) { + kim_string_free ((kim_string *) &reply); + } else { + kim_ui_free_string (context, &reply); + } } } @@ -299,12 +292,12 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, #ifndef LEAN_CLIENT } else if (in_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_change_password ((kim_ui_gui_context) in_context->tcontext, - in_identity, - in_old_password_expired, - out_old_password, - out_new_password, - out_verify_password); + err = kim_os_ui_gui_change_password ((kim_ui_gui_context) in_context->tcontext, + in_identity, + in_old_password_expired, + out_old_password, + out_new_password, + out_verify_password); } else if (in_context->type == kim_ui_type_cli) { err = kim_ui_cli_change_password ((kim_ui_cli_context) in_context->tcontext, @@ -313,14 +306,13 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, out_old_password, out_new_password, out_verify_password); - #endif /* LEAN_CLIENT */ } else { err = check_error (KIM_NO_UI_ERR); } } - + return check_error (err); } @@ -338,14 +330,14 @@ kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, if (!err) { /* Do this first so last error doesn't get overwritten */ - err = kim_string_get_last_error_message (&description, in_error); + err = kim_string_create_for_last_error (&description, in_error); } if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { kim_string key = NULL; - + switch (in_type) { case kim_ui_error_type_authentication: key = "KLStringLoginFailed"; @@ -361,7 +353,7 @@ kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, key = "KLStringKerberosOperationFailed"; break; } - + err = kim_os_string_create_localized (&message, key); } @@ -393,25 +385,25 @@ kim_error kim_ui_handle_error (kim_ui_context *in_context, if (!err) { if (in_context->type == kim_ui_type_gui_plugin) { err = kim_ui_plugin_handle_error ((kim_ui_plugin_context) in_context->tcontext, - in_identity, - in_error, - in_error_message, - in_error_description); + in_identity, + in_error, + in_error_message, + in_error_description); #ifndef LEAN_CLIENT } else if (in_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_handle_error ((kim_ui_gui_context) in_context->tcontext, - in_identity, - in_error, - in_error_message, - in_error_description); + err = kim_os_ui_gui_handle_error ((kim_ui_gui_context) in_context->tcontext, + in_identity, + in_error, + in_error_message, + in_error_description); } else if (in_context->type == kim_ui_type_cli) { err = kim_ui_cli_handle_error ((kim_ui_cli_context) in_context->tcontext, - in_identity, - in_error, - in_error_message, - in_error_description); + in_identity, + in_error, + in_error_message, + in_error_description); #endif /* LEAN_CLIENT */ } else { @@ -434,8 +426,8 @@ void kim_ui_free_string (kim_ui_context *in_context, #ifndef LEAN_CLIENT } else if (in_context->type == kim_ui_type_gui_builtin) { - kim_ui_gui_free_string ((kim_ui_gui_context) in_context->tcontext, - io_string); + kim_os_ui_gui_free_string ((kim_ui_gui_context) in_context->tcontext, + io_string); } else if (in_context->type == kim_ui_type_cli) { kim_ui_cli_free_string ((kim_ui_cli_context) in_context->tcontext, @@ -455,14 +447,12 @@ kim_error kim_ui_fini (kim_ui_context *io_context) if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - kim_identity_free (&io_context->identity); - if (io_context->type == kim_ui_type_gui_plugin) { err = kim_ui_plugin_fini ((kim_ui_plugin_context *) &io_context->tcontext); #ifndef LEAN_CLIENT } else if (io_context->type == kim_ui_type_gui_builtin) { - err = kim_ui_gui_fini ((kim_ui_gui_context *) &io_context->tcontext); + err = kim_os_ui_gui_fini ((kim_ui_gui_context *) &io_context->tcontext); } else if (io_context->type == kim_ui_type_cli) { err = kim_ui_cli_fini ((kim_ui_cli_context *) &io_context->tcontext); diff --git a/src/kim/lib/kim_ui_gui_private.h b/src/kim/lib/kim_ui_gui_private.h index b6d2ebd52..9792f53d5 100644 --- a/src/kim/lib/kim_ui_gui_private.h +++ b/src/kim/lib/kim_ui_gui_private.h @@ -35,41 +35,41 @@ struct kim_ui_gui_context; typedef struct kim_ui_gui_context *kim_ui_gui_context; -kim_error kim_ui_gui_init (kim_ui_gui_context *out_context); +kim_error kim_os_ui_gui_init (kim_ui_gui_context *out_context); -kim_error kim_ui_gui_enter_identity (kim_ui_gui_context in_context, - kim_identity *out_identity); +kim_error kim_os_ui_gui_enter_identity (kim_ui_gui_context in_context, + kim_identity *out_identity); -kim_error kim_ui_gui_select_identity (kim_ui_gui_context in_context, - kim_selection_hints in_hints, - kim_identity *out_identity); +kim_error kim_os_ui_gui_select_identity (kim_ui_gui_context in_context, + kim_selection_hints in_hints, + kim_identity *out_identity); -kim_error kim_ui_gui_auth_prompt (kim_ui_gui_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_gui_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_ui_gui_change_password (kim_ui_gui_context in_context, - kim_identity in_identity, - kim_boolean in_old_password_expired, - char **out_old_password, - char **out_new_password, - char **out_verify_password); +kim_error kim_os_ui_gui_change_password (kim_ui_gui_context in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); -kim_error kim_ui_gui_handle_error (kim_ui_gui_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description); +kim_error kim_os_ui_gui_handle_error (kim_ui_gui_context in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); -void kim_ui_gui_free_string (kim_ui_gui_context in_context, - char **io_string); +void kim_os_ui_gui_free_string (kim_ui_gui_context in_context, + char **io_string); -kim_error kim_ui_gui_fini (kim_ui_gui_context *io_context); +kim_error kim_os_ui_gui_fini (kim_ui_gui_context *io_context); #endif /* LEAN_CLIENT */ diff --git a/src/kim/lib/kim_ui_private.h b/src/kim/lib/kim_ui_private.h index 817a4b29f..abaffcf04 100644 --- a/src/kim/lib/kim_ui_private.h +++ b/src/kim/lib/kim_ui_private.h @@ -50,12 +50,6 @@ typedef struct kim_ui_context { kim_identity identity; } kim_ui_context; -krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, - void *in_context, - const char *in_name, - const char *in_banner, - int in_num_prompts, - krb5_prompt in_prompts[]); kim_error kim_ui_init (kim_ui_context *io_context); @@ -67,14 +61,12 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, kim_selection_hints in_hints, kim_identity *out_identity); -kim_error kim_ui_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); +krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, + void *in_context, + const char *in_name, + const char *in_banner, + int in_num_prompts, + krb5_prompt in_prompts[]); kim_error kim_ui_change_password (kim_ui_context *in_context, kim_identity in_identity, diff --git a/src/kim/lib/kim_ui_gui.c b/src/kim/lib/mac/kim_os_ui_gui.c similarity index 68% rename from src/kim/lib/kim_ui_gui.c rename to src/kim/lib/mac/kim_os_ui_gui.c index 9eb41e457..c755a7894 100644 --- a/src/kim/lib/kim_ui_gui.c +++ b/src/kim/lib/mac/kim_os_ui_gui.c @@ -35,7 +35,7 @@ struct kim_ui_gui_context { /* ------------------------------------------------------------------------ */ -static void kim_ui_gui_context_free (kim_ui_gui_context *io_context) +static void kim_os_ui_gui_context_free (kim_ui_gui_context *io_context) { if (io_context && *io_context) { free (*io_context); @@ -45,7 +45,7 @@ static void kim_ui_gui_context_free (kim_ui_gui_context *io_context) /* ------------------------------------------------------------------------ */ -static kim_error kim_ui_gui_context_allocate (kim_ui_gui_context *out_context) +static kim_error kim_os_ui_gui_context_allocate (kim_ui_gui_context *out_context) { kim_error err = KIM_NO_ERROR; kim_ui_gui_context context = NULL; @@ -62,7 +62,7 @@ static kim_error kim_ui_gui_context_allocate (kim_ui_gui_context *out_context) context = NULL; } - kim_ui_gui_context_free (&context); + kim_os_ui_gui_context_free (&context); return check_error (err); } @@ -71,7 +71,7 @@ static kim_error kim_ui_gui_context_allocate (kim_ui_gui_context *out_context) /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_init (kim_ui_gui_context *out_context) +kim_error kim_os_ui_gui_init (kim_ui_gui_context *out_context) { kim_error err = KIM_NO_ERROR; kim_ui_gui_context context = NULL; @@ -79,7 +79,7 @@ kim_error kim_ui_gui_init (kim_ui_gui_context *out_context) if (!err && !out_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - err = kim_ui_gui_context_allocate (&context); + err = kim_os_ui_gui_context_allocate (&context); } if (!err) { @@ -90,15 +90,15 @@ kim_error kim_ui_gui_init (kim_ui_gui_context *out_context) context = NULL; } - kim_ui_gui_context_free (&context); + kim_os_ui_gui_context_free (&context); return check_error (err); } /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_enter_identity (kim_ui_gui_context in_context, - kim_identity *out_identity) +kim_error kim_os_ui_gui_enter_identity (kim_ui_gui_context in_context, + kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; @@ -113,9 +113,9 @@ kim_error kim_ui_gui_enter_identity (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_select_identity (kim_ui_gui_context in_context, - kim_selection_hints in_hints, - kim_identity *out_identity) +kim_error kim_os_ui_gui_select_identity (kim_ui_gui_context in_context, + kim_selection_hints in_hints, + kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; @@ -131,14 +131,14 @@ kim_error kim_ui_gui_select_identity (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_auth_prompt (kim_ui_gui_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_gui_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 err = KIM_NO_ERROR; @@ -155,12 +155,12 @@ kim_error kim_ui_gui_auth_prompt (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_change_password (kim_ui_gui_context in_context, - kim_identity in_identity, - kim_boolean in_old_password_expired, - char **out_old_password, - char **out_new_password, - char **out_verify_password) +kim_error kim_os_ui_gui_change_password (kim_ui_gui_context in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password) { kim_error err = KIM_NO_ERROR; @@ -178,11 +178,11 @@ kim_error kim_ui_gui_change_password (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_handle_error (kim_ui_gui_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description) +kim_error kim_os_ui_gui_handle_error (kim_ui_gui_context in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) { kim_error err = KIM_NO_ERROR; @@ -198,15 +198,15 @@ kim_error kim_ui_gui_handle_error (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -void kim_ui_gui_free_string (kim_ui_gui_context in_context, - char **io_string) +void kim_os_ui_gui_free_string (kim_ui_gui_context in_context, + char **io_string) { kim_string_free ((kim_string *) io_string); } /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_fini (kim_ui_gui_context *io_context) +kim_error kim_os_ui_gui_fini (kim_ui_gui_context *io_context) { kim_error err = KIM_NO_ERROR; @@ -216,7 +216,7 @@ kim_error kim_ui_gui_fini (kim_ui_gui_context *io_context) } if (!err) { - kim_ui_gui_context_free (io_context); + kim_os_ui_gui_context_free (io_context); } -- 2.26.2