From 5e158de9231f955c9bb017981ded6ce6019e7abe Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Mon, 22 Sep 2008 22:13:06 +0000 Subject: [PATCH] Added command line UI support. Added change password and acquire credentials UI harness support. API changes to the change password support to reflect these changes. Removed callback prompter interfaces since there is now plugin support. Updated documentation. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20745 dc483132-0cff-0310-8789-dd5450dbe970 --- ...oup__kim__ccache__iterator__reference.html | 2 +- .../html/group__kim__ccache__reference.html | 2 +- ..._kim__credential__iterator__reference.html | 2 +- .../group__kim__credential__reference.html | 121 +- .../html/group__kim__error__reference.html | 2 +- .../html/group__kim__identity__reference.html | 73 +- .../html/group__kim__options__reference.html | 170 +-- .../group__kim__preferences__reference.html | 2 +- ...oup__kim__selection__hints__reference.html | 2 +- .../html/group__kim__string__reference.html | 2 +- .../html/group__kim__types__reference.html | 234 +--- doc/kim/html/index.html | 2 +- doc/kim/html/kim_ccache_overview.html | 2 +- doc/kim/html/kim_credential_overview.html | 2 +- doc/kim/html/kim_error_overview.html | 2 +- doc/kim/html/kim_identity_overview.html | 4 +- doc/kim/html/kim_options_overview.html | 10 +- doc/kim/html/kim_preferences_overview.html | 2 +- .../html/kim_selection_hints_overview.html | 2 +- doc/kim/html/kim_string_overview.html | 2 +- doc/kim/html/modules.html | 2 +- src/include/kim/kim_credential.h | 1004 +++++++++-------- src/include/kim/kim_identity.h | 21 +- src/include/kim/kim_options.h | 147 --- src/include/kim/kim_ui_plugin.h | 55 +- src/kim/lib/kim-lite.exports | 12 +- src/kim/lib/kim.exports | 8 +- src/kim/lib/kim_credential.c | 336 +++++- src/kim/lib/kim_identity.c | 116 +- src/kim/lib/kim_options.c | 176 +-- src/kim/lib/kim_selection_hints.c | 14 +- src/kim/lib/kim_string.c | 1 + src/kim/lib/kim_string_private.h | 4 + src/kim/lib/kim_ui.c | 212 +++- src/kim/lib/kim_ui_cli.c | 324 +++++- src/kim/lib/kim_ui_cli_private.h | 24 +- src/kim/lib/kim_ui_gui.c | 44 +- src/kim/lib/kim_ui_gui_private.h | 14 +- src/kim/lib/kim_ui_plugin.c | 44 +- src/kim/lib/kim_ui_plugin_private.h | 18 +- src/kim/lib/kim_ui_private.h | 39 +- src/kim/lib/mac/kim_os_library.c | 2 + src/kim/lib/mac/kim_os_string.c | 49 +- 43 files changed, 1855 insertions(+), 1451 deletions(-) diff --git a/doc/kim/html/group__kim__ccache__iterator__reference.html b/doc/kim/html/group__kim__ccache__iterator__reference.html index 9a4692dfb..1c5700d76 100644 --- a/doc/kim/html/group__kim__ccache__iterator__reference.html +++ b/doc/kim/html/group__kim__ccache__iterator__reference.html @@ -107,7 +107,7 @@ Free memory associated with a ccache iterator.

-


Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
diff --git a/doc/kim/html/group__kim__ccache__reference.html b/doc/kim/html/group__kim__ccache__reference.html index 884739c55..025b166a8 100644 --- a/doc/kim/html/group__kim__ccache__reference.html +++ b/doc/kim/html/group__kim__ccache__reference.html @@ -977,7 +977,7 @@ Free memory associated with a ccache.

-


Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
diff --git a/doc/kim/html/group__kim__credential__iterator__reference.html b/doc/kim/html/group__kim__credential__iterator__reference.html index 81c8ab157..1bcae59b0 100644 --- a/doc/kim/html/group__kim__credential__iterator__reference.html +++ b/doc/kim/html/group__kim__credential__iterator__reference.html @@ -117,7 +117,7 @@ Free memory associated with a credential iterator.

-


Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
diff --git a/doc/kim/html/group__kim__credential__reference.html b/doc/kim/html/group__kim__credential__reference.html index df5250239..460b065ae 100644 --- a/doc/kim/html/group__kim__credential__reference.html +++ b/doc/kim/html/group__kim__credential__reference.html @@ -12,7 +12,8 @@
  • kim_error kim_credential_create_new (kim_credential *out_credential, kim_identity in_client_identity, kim_options in_options)
    Acquire a new initial credential.
  • kim_error kim_credential_create_from_keytab (kim_credential *out_credential, kim_identity in_identity, kim_options in_options, kim_string in_keytab)
    Acquire a new initial credential from a keytab.
  • kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, krb5_context in_krb5_context, krb5_creds *in_krb5_creds) -
    Copy a credential from a krb5 credential object.
  • kim_error kim_credential_copy (kim_credential *out_credential, kim_credential in_credential) +
    Copy a credential from a krb5 credential object.
  • kim_error kim_credential_create_for_change_password (kim_credential *out_credential, kim_identity in_identity, kim_string in_old_password) +
    Obtain a credential for changing an identity's password.
  • kim_error kim_credential_copy (kim_credential *out_credential, kim_credential in_credential)
    Copy a credential object.
  • kim_error kim_credential_get_krb5_creds (kim_credential in_credential, krb5_context in_krb5_context, krb5_creds **out_krb5_creds)
    Get a krb5 credentials object for a credential object.
  • kim_error kim_credential_get_client_identity (kim_credential in_credential, kim_identity *out_client_identity)
    Get the client identity of a credential object.
  • kim_error kim_credential_get_service_identity (kim_credential in_credential, kim_identity *out_service_identity) @@ -25,7 +26,8 @@
    Store a credential in a ccache in the cache collection.
  • kim_error kim_credential_verify (kim_credential in_credential, kim_identity in_service_identity, kim_string in_keytab, kim_boolean in_fail_if_no_service_key)
    Verify a TGT credential.
  • kim_error kim_credential_renew (kim_credential *io_credential, kim_options in_options)
    Renew a TGT credential.
  • kim_error kim_credential_validate (kim_credential *io_credential, kim_options in_options) -
    Validate a TGT credential.
  • void kim_credential_free (kim_credential *io_credential) +
    Validate a TGT credential.
  • kim_error kim_credential_change_password (kim_credential in_credential, kim_identity in_identity, kim_string in_new_password, kim_error *out_rejected_err, kim_string *out_rejected_message, kim_string *out_rejected_description) +
    Change an identity's password.
  • void kim_credential_free (kim_credential *io_credential)
    Free memory associated with a credential object.

    Function Documentation

    @@ -171,6 +173,52 @@ Copy a credential from a krb5 credential object.
    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    + +

    + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    kim_error kim_credential_create_for_change_password (kim_credential out_credential,
    kim_identity  in_identity,
    kim_string  in_old_password 
    )
    +
    +
    + +

    +Obtain a credential for changing an identity's password. +

    +

    Parameters:
    + + + + +
    out_credential on exit, a new credential object containing a change password credential for in_identity. Must be freed with kim_credential_free().
    in_identity a client identity to obtain a change password credential for.
    in_old_password the current password for in_identity. May be an expired password.
    +
    +
    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    +
    See also:
    kim_credential_change_password
    +

    @@ -700,6 +748,73 @@ Validate a TGT credential.

    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    See also:
    kim_ccache_validate
    + +

    + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    kim_error kim_credential_change_password (kim_credential  in_credential,
    kim_identity  in_identity,
    kim_string  in_new_password,
    kim_error out_rejected_err,
    kim_string out_rejected_message,
    kim_string out_rejected_description 
    )
    +
    +
    + +

    +Change an identity's password. +

    +

    Parameters:
    + + + + + + + +
    in_credential a credential object containing a change password credential. Use kim_credential_change_password to obtain a change password credential.
    in_identity an identity to change the password for. May be different than the identity the credential is for.
    in_new_password the password to change the identity to.
    out_rejected_err on exit, 0 if the password change was successful or an error describing why the new password was rejected.
    out_rejected_message on exit, if out_rejected_err is non-zero this argument will contain an error message for out_rejected_err. Pass NULL if you do not want this error string. Must be freed with kim_string_free();
    out_rejected_description on exit, if out_rejected_err is non-zero this argument will contain an string describing why in_new_password was rejected. Pass NULL if you do not want this error string. Must be freed with kim_string_free();
    +
    +
    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    +
    See also:
    kim_credential_create_for_change_password
    +

    @@ -729,7 +844,7 @@ Free memory associated with a credential object.

    -


    Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
    Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
    diff --git a/doc/kim/html/group__kim__error__reference.html b/doc/kim/html/group__kim__error__reference.html index df2723664..8cba97787 100644 --- a/doc/kim/html/group__kim__error__reference.html +++ b/doc/kim/html/group__kim__error__reference.html @@ -51,7 +51,7 @@ Get a text description of an error suitable for display to the user.

    -


    Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
    Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
    diff --git a/doc/kim/html/group__kim__identity__reference.html b/doc/kim/html/group__kim__identity__reference.html index f20544fd3..9895406a2 100644 --- a/doc/kim/html/group__kim__identity__reference.html +++ b/doc/kim/html/group__kim__identity__reference.html @@ -20,9 +20,8 @@
    Get the realm string of an identity.
  • kim_error kim_identity_get_number_of_components (kim_identity in_identity, kim_count *out_number_of_components)
    Get the number of components of an identity.
  • kim_error kim_identity_get_component_at_index (kim_identity in_identity, kim_count in_index, kim_string *out_component_string)
    Get the Nth component of an identity.
  • kim_error kim_identity_get_krb5_principal (kim_identity in_identity, krb5_context in_krb5_context, krb5_principal *out_krb5_principal) -
    Get the krb5_principal representation of an identity.
  • kim_error kim_identity_change_password (kim_identity in_identity, kim_options in_options) -
    Change the password for an identity.
  • kim_error kim_identity_change_password_to_password (kim_identity in_identity, kim_options in_options, kim_string in_new_password) -
    Change the password for an identity to a caller-provided new password.
  • void kim_identity_free (kim_identity *io_identity) +
    Get the krb5_principal representation of an identity.
  • kim_error kim_identity_change_password (kim_identity in_identity) +
    Change the password for an identity.
  • void kim_identity_free (kim_identity *io_identity)
    Free memory associated with an identity.

    Function Documentation

    @@ -488,7 +487,7 @@ Get the krb5_principal representation of an identity.

    - +

    @@ -496,18 +495,9 @@ Get the krb5_principal representation of an identity. - - - - - - - - - - - - + + +
    kim_error kim_identity_change_password ( kim_identity  in_identity,
    kim_options  in_options 
    ) in_identity  ) 
    @@ -519,57 +509,10 @@ Change the password for an identity.
    Parameters:
    - -
    in_identity an identity object whose password will be changed.
    in_options initial credential options to be used if a new credential is obtained.
    -
    -
    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    -
    Note:
    kim_identity_change_password() will acquire a temporary credential to change the password. It uses the in_options structure to obtain information about the desired prompter and current password.
    - -
    -

    - -

    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    kim_error kim_identity_change_password_to_password (kim_identity  in_identity,
    kim_options  in_options,
    kim_string  in_new_password 
    )
    -
    -
    - -

    -Change the password for an identity to a caller-provided new password. -

    -

    Parameters:
    - - - -
    in_identity an identity object whose password will be changed.
    in_options initial credential options to be used if a new credential is obtained.
    in_new_password a string representation of the identity's new password.
    Returns:
    On success, KIM_NO_ERROR. On failure, an error code representing the failure.
    -
    Note:
    kim_identity_change_password_with_passwords() will acquire a temporary credential to change the password. It uses the in_options structure to obtain information about the desired prompter and current password.
    +
    Note:
    kim_identity_change_password() will acquire a temporary credential to change the password.

    @@ -600,7 +543,7 @@ Free memory associated with an identity.

    -


    Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
    Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
    diff --git a/doc/kim/html/group__kim__options__reference.html b/doc/kim/html/group__kim__options__reference.html index 0d7536473..6a170668d 100644 --- a/doc/kim/html/group__kim__options__reference.html +++ b/doc/kim/html/group__kim__options__reference.html @@ -11,11 +11,7 @@
    • kim_error kim_options_create (kim_options *out_options)
      Create new options with default values.
    • kim_error kim_options_copy (kim_options *out_options, kim_options in_options) -
      Copy options.
    • kim_error kim_options_set_prompt_callback (kim_options io_options, kim_prompt_callback in_prompt_callback) -
      Set the prompt callback for obtaining information from the user.
    • kim_error kim_options_get_prompt_callback (kim_options in_options, kim_prompt_callback *out_prompt_callback) -
      Get the prompt callback for obtaining information from the user.
    • kim_error kim_options_set_data (kim_options io_options, const void *in_data) -
      Set caller-specific data for use in library callbacks.
    • kim_error kim_options_get_data (kim_options in_options, const void **out_data) -
      Get caller-specific data for use in library callbacks.
    • kim_error kim_options_set_start_time (kim_options io_options, kim_time in_start_time) +
      Copy options.
    • kim_error kim_options_set_start_time (kim_options io_options, kim_time in_start_time)
      Set the date when a credential should become valid.
    • kim_error kim_options_get_start_time (kim_options in_options, kim_time *out_start_time)
      Get the date when a credential should become valid.
    • kim_error kim_options_set_lifetime (kim_options io_options, kim_lifetime in_lifetime)
      Set the duration during which a credential should be valid.
    • kim_error kim_options_get_lifetime (kim_options in_options, kim_lifetime *out_lifetime) @@ -98,168 +94,6 @@ Copy options.
      Returns:
      On success, KIM_NO_ERROR. On failure, an error code representing the failure.
      - -

      - -

      -
      - - - - - - - - - - - - - - - - - - -
      kim_error kim_options_set_prompt_callback (kim_options  io_options,
      kim_prompt_callback  in_prompt_callback 
      )
      -
      -
      - -

      -Set the prompt callback for obtaining information from the user. -

      -

      Parameters:
      - - - -
      io_options an options object to modify.
      in_prompt_callback a prompt callback function.
      -
      -
      Returns:
      On success, KIM_NO_ERROR. On failure, an error code representing the failure.
      -
      Default value
      kim_prompt_callback_default
      -
      See also:
      kim_options_get_prompt_callback()
      - -
      -

      - -

      -
      - - - - - - - - - - - - - - - - - - -
      kim_error kim_options_get_prompt_callback (kim_options  in_options,
      kim_prompt_callback out_prompt_callback 
      )
      -
      -
      - -

      -Get the prompt callback for obtaining information from the user. -

      -

      Parameters:
      - - - -
      in_options an options object.
      out_prompt_callback on exit, the prompt callback specified by in_options. Does not need to be freed but may become invalid when in_options is freed.
      -
      -
      Returns:
      On success, KIM_NO_ERROR. On failure, an error code representing the failure.
      -
      Default value
      kim_prompt_callback_default
      -
      See also:
      kim_options_set_prompt_callback()
      - -
      -

      - -

      -
      - - - - - - - - - - - - - - - - - - -
      kim_error kim_options_set_data (kim_options  io_options,
      const void *  in_data 
      )
      -
      -
      - -

      -Set caller-specific data for use in library callbacks. -

      -

      Parameters:
      - - - -
      io_options an options object to modify.
      in_data a pointer to caller-specific data.
      -
      -
      Returns:
      On success, KIM_NO_ERROR. On failure, an error code representing the failure.
      -
      Note:
      This option can be used by the caller to store a pointer to data needed when handling a callback. The KIM library does not use this options data in any way.
      -
      Default value
      NULL (no data is set by default)
      -
      See also:
      kim_options_get_data()
      - -
      -

      - -

      -
      - - - - - - - - - - - - - - - - - - -
      kim_error kim_options_get_data (kim_options  in_options,
      const void **  out_data 
      )
      -
      -
      - -

      -Get caller-specific data for use in library callbacks. -

      -

      Parameters:
      - - - -
      in_options an options object.
      out_data on exit, the pointer to caller specific data specified by in_options. Does not need to be freed but may become invalid when in_options is freed.
      -
      -
      Returns:
      On success, KIM_NO_ERROR. On failure, an error code representing the failure.
      -
      Note:
      This option can be used by the caller to store a pointer to data needed when handling a callback. The KIM library does not use this options data in any way.
      -
      Default value
      NULL (no data is set by default)
      -
      See also:
      kim_options_set_data()
      -

      @@ -935,7 +769,7 @@ Free memory associated with an options object.

      -


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/group__kim__preferences__reference.html b/doc/kim/html/group__kim__preferences__reference.html index 70ed55e94..918a46465 100644 --- a/doc/kim/html/group__kim__preferences__reference.html +++ b/doc/kim/html/group__kim__preferences__reference.html @@ -982,7 +982,7 @@ Free memory associated with a preferences object.

      -


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/group__kim__selection__hints__reference.html b/doc/kim/html/group__kim__selection__hints__reference.html index 4676c7a4f..06c414464 100644 --- a/doc/kim/html/group__kim__selection__hints__reference.html +++ b/doc/kim/html/group__kim__selection__hints__reference.html @@ -740,7 +740,7 @@ Free memory associated with a selection hints object.

      -


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/group__kim__string__reference.html b/doc/kim/html/group__kim__string__reference.html index df2493dd1..a7ae6aa66 100644 --- a/doc/kim/html/group__kim__string__reference.html +++ b/doc/kim/html/group__kim__string__reference.html @@ -164,7 +164,7 @@ Free memory associated with a string.

      -


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/group__kim__types__reference.html b/doc/kim/html/group__kim__types__reference.html index 3654b9deb..473292d25 100644 --- a/doc/kim/html/group__kim__types__reference.html +++ b/doc/kim/html/group__kim__types__reference.html @@ -20,8 +20,6 @@

      Typedefs


      Define Documentation

      @@ -206,36 +194,6 @@ Convenience macro for interpreting kim_comparison_t. The state of a credential. See kim_credential_state_enum for possible values.

      - -

      -
      - - - - -
      typedef uint32_t kim_prompt_type
      -
      -
      - -

      -The type of prompt which needs to be displayed. This value determines what type of user interface is displayed. See Providing a Custom Prompt Callback for more information. -

      -

      - -

      -
      - - - - -
      typedef kim_error(* kim_prompt_callback)(kim_prompt_type in_type, kim_string in_title, kim_string in_message, kim_string in_description, char **out_reply)
      -
      -
      - -

      -The prompt callback used to display a prompt to the user. See Providing a Custom Prompt Callback for more information. -

      -

      @@ -505,197 +463,7 @@ Possible credential states. Credentials may be:

      -


      Function Documentation

      - -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      kim_error kim_prompt_callback_default (kim_prompt_type  in_type,
      kim_string  in_title,
      kim_string  in_message,
      kim_string  in_description,
      char **  out_reply 
      )
      -
      -
      - -

      -The default prompt callback. See Providing a Custom Prompt Callback for more information. -

      -

      - -

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      kim_error kim_prompt_callback_gui (kim_prompt_type  in_type,
      kim_string  in_title,
      kim_string  in_message,
      kim_string  in_description,
      char **  out_reply 
      )
      -
      -
      - -

      -The graphical prompt callback. See Providing a Custom Prompt Callback for more information. -

      -

      - -

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      kim_error kim_prompt_callback_cli (kim_prompt_type  in_type,
      kim_string  in_title,
      kim_string  in_message,
      kim_string  in_description,
      char **  out_reply 
      )
      -
      -
      - -

      -The command line prompt callback. See Providing a Custom Prompt Callback for more information. -

      -

      - -

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      kim_error kim_prompt_callback_none (kim_prompt_type  in_type,
      kim_string  in_title,
      kim_string  in_message,
      kim_string  in_description,
      char **  out_reply 
      )
      -
      -
      - -

      -The prompt callback which always returns an error. Use to turn off prompting entirely.

      Note:
      Using this callback may prevent the user from authenicating. See Providing a Custom Prompt Callback for more information.
      - -
      -

      -


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/index.html b/doc/kim/html/index.html index ae9473c86..577f31130 100644 --- a/doc/kim/html/index.html +++ b/doc/kim/html/index.html @@ -82,7 +82,7 @@ Types and Constants -
      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_ccache_overview.html b/doc/kim/html/kim_ccache_overview.html index 16bcf1424..04fe924a3 100644 --- a/doc/kim/html/kim_ccache_overview.html +++ b/doc/kim/html/kim_ccache_overview.html @@ -59,7 +59,7 @@ Examining CCache Properties
      • kim_ccache_get_renewal_expiration_time() returns when the credential's in a ccache will no longer be renewable. Valid credentials may be renewed up until their renewal expiration time. Renewing credentials acquires a fresh set of credentials with a full lifetime without resending secrets to the KDC (such as a password). If credentials are not renewable, this function will return an error.
      -See KIM CCache Reference Documentation and KIM CCache Iterator Reference Documentation for information on specific APIs.
      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM CCache Reference Documentation and KIM CCache Iterator Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_credential_overview.html b/doc/kim/html/kim_credential_overview.html index 6b47baf76..5e0a5e049 100644 --- a/doc/kim/html/kim_credential_overview.html +++ b/doc/kim/html/kim_credential_overview.html @@ -56,7 +56,7 @@ Examining Credential Properties
      • kim_credential_get_renewal_expiration_time() returns when the credential will no longer be renewable. Valid credentials may be renewed up until their renewal expiration time. Renewing credentials acquires a fresh set of credentials with a full lifetime without resending secrets to the KDC (such as a password). If credentials are not renewable, this function will return an error.
      -See KIM Credential Reference Documentation and KIM Credential Iterator Reference Documentation for information on specific APIs.
      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Credential Reference Documentation and KIM Credential Iterator Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_error_overview.html b/doc/kim/html/kim_error_overview.html index b8d02df68..7a3f01844 100644 --- a/doc/kim/html/kim_error_overview.html +++ b/doc/kim/html/kim_error_overview.html @@ -9,7 +9,7 @@ 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 KIM Error Reference Documentation for information on specific APIs.


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Error Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_identity_overview.html b/doc/kim/html/kim_identity_overview.html index 93ee11d24..86717be66 100644 --- a/doc/kim/html/kim_identity_overview.html +++ b/doc/kim/html/kim_identity_overview.html @@ -34,9 +34,9 @@ Unfortunately most of the time applications don't know what client identity to u To solve this problem, kim_selection_hints_get_identity() takes information from the application in the form of a selection hints object and returns the best matching client identity, if one is available. See KIM Selection Hints Overview for more information.

      Changing a Identity's Password

      Many Kerberos sites use passwords for user accounts. Because passwords may be stolen or compromised, they must be frequently changed. KIM provides APIs to change the identity's password directly, and also handles changing the identity's password when it has expired.

      -kim_identity_change_password() presents a user interface to obtain the old and new passwords from the user. kim_identity_change_password_with_passwords() takes the old and new passwords as input, but may still present a user interface if it needs to obtain additional information to authenticate.

      +kim_identity_change_password() presents a user interface to obtain the old and new passwords from the user. kim_identity_change_password_with_passwords() takes the old and new passwords as input, but may still present a user interface if it needs to obtain additional information to authenticate.

      Note:
      Not all identities have a password. Some sites use certificates (pkinit) and in the future there may be other authentication mechanisms (eg: smart cards).
      -See KIM Identity Reference Documentation for information on specific APIs.
      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Identity Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_options_overview.html b/doc/kim/html/kim_options_overview.html index f5e42c355..2273edebc 100644 --- a/doc/kim/html/kim_options_overview.html +++ b/doc/kim/html/kim_options_overview.html @@ -8,13 +8,7 @@

      KIM Options Overview

      Introduction

      Kerberos Identity Management Options (kim_options_t) allows you to control how the Kerberos library obtains credentials. When the options structure is initialized with kim_options_create(), each option is filled in with a default value which can then be modified with the kim_options_set_*() APIs. If you only want to use the default values, you may pass KIM_OPTIONS_DEFAULT into any KIM function that takes a kim_options_t.

      -KIM options fall into two major categories: options for controlling how credentials are acquired and options for controlling what properties the newly acquired credentials will have:

      -Options for Controlling Credential Acquisition

      -In order to acquire credentials, Kerberos needs to obtain one or more secrets from the user. These secrets may be a certificate, password, SecurID pin, or information from a smart card. If obtaining the secret requires interaction with the user, the Kerberos libraries call a "prompter callback" to display a dialog or command line prompt to request information from the user. If you want to provide your own custom dialogs or command line prompts, the KIM APIs provide a mechanism for replacing the default prompt callbacks with your own.

      -Providing a Custom Prompt Callback

      -All secrets are obtained from the user through a kim_prompt_callback_t. By default, options use kim_prompt_callback_default, which presents a dialog to request information from the user, or if no graphical access is available, a command line prompt.

      -KIM also provides three other callbacks: kim_prompt_callback_gui only presents a dialog and returns an error if there is no graphical access. kim_prompt_callback_cli only presents a command line interface and returns an error if there is no controlling terminal available. kim_prompt_callback_none always returns an error.

      -Using kim_options_set_prompt_callback(), you can change the prompt callback to one of the above callbacks or a callback you have defined yourself. Callbacks are called in a loop, one for each prompt. Because network traffic may occur between calls to the prompt callback, your prompt interface should support time passing between calls to the prompter. If you are defining a callback yourself, you should also set your own options data with kim_options_set_data() for storing state between calls. Options data is a caller defined pointer value -- the Kerberos libaries make no use of it.

      +KIM options fall into two major categories: options for controlling how credentials are acquired and options for controlling what properties the newly acquired credentials will have:

      Options for Controlling Credential Properties

      Kerberos credentials have a number of different properties which can be requested when credentials are acquired. These properties control when and for how long the credentials are valid and what you can do with them.

      Note that setting these properties in the KIM options only changes what the Kerberos libraries request from the KDC. The KDC itself may choose not to honor your requested properties if they violate the site security policy. For example, most sites place an upper bound on how long credentials may be valid. If you request a credential lifetime longer than this upper bound, the KDC may return credentials with a shorter lifetime than you requested.

      @@ -39,7 +33,7 @@ Like forwardability, the proxiable flag only applies to TGT credentials. Unlike Use kim_options_set_proxiable() to change whether or not the Kerberos libraries request proxiable credentials. Use kim_options_get_proxiable() to find out the current setting.

      Service Name

      Normally users acquire TGT credentials (ie "ticket granting tickets") and then use those credentials to acquire service credentials. This allows Kerberos to provide single sign-on while still providing mutual authentication to services. However, sometimes you just want an initial credential for a service. KIM options allows you to set the service name with kim_options_set_service_name() and query it with kim_options_get_service_name().

      -See KIM Options Reference Documentation for information on specific APIs.


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Options Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_preferences_overview.html b/doc/kim/html/kim_preferences_overview.html index c42e0878b..cb12608ca 100644 --- a/doc/kim/html/kim_preferences_overview.html +++ b/doc/kim/html/kim_preferences_overview.html @@ -29,7 +29,7 @@ Viewing and Editing the Favorite Identities First, you need to acquire the Favorite Identities stored in the user's preferences using kim_preferences_create().

      Then use kim_preferences_get_number_of_favorite_identities() and kim_preferences_get_favorite_identity_at_index() to display the identities list. Use kim_preferences_add_favorite_identity() and kim_preferences_remove_favorite_identity() to change which identities are in the identities list. Identities are always stored in alphabetical order and duplicate identities are not permitted, so when you add or remove a identity you should redisplay the entire list. If you wish to replace the identities list entirely, use kim_preferences_remove_all_favorite_identities() to clear the list before adding your identities.

      Once you are done editing the favorite identities list, store changes in the user's preference file using kim_preferences_synchronize().

      -See KIM Preferences Documentation for information on specific APIs.


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Preferences Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_selection_hints_overview.html b/doc/kim/html/kim_selection_hints_overview.html index b8428b885..f30bed3ad 100644 --- a/doc/kim/html/kim_selection_hints_overview.html +++ b/doc/kim/html/kim_selection_hints_overview.html @@ -48,7 +48,7 @@ In order to let the user know why Kerberos needs their assistance, KIM displays In many cases a single application may select different identities for different purposes. For example an email application might use different identities to check mail for different accounts. If your application has this property you may need to provide the user with a localized string describing how the identity will be used. You can specify this string with kim_selection_hints_get_explanation(). You can find out what string will be used with kim_selection_hints_set_explanation().

      Since the user may choose to acquire credentials when selection an identity, KIM also provides kim_selection_hints_set_options() to set what credential acquisition options are used. kim_selection_hints_get_options() returns the options which will be used.

      If you need to disable user interaction, use kim_selection_hints_set_allow_user_interaction(). Use kim_selection_hints_get_allow_user_interaction() to find out whether or not user interaction is enabled. User interaction is enabled by default.

      -See KIM Selection Hints Reference Documentation for information on specific APIs.


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM Selection Hints Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/kim_string_overview.html b/doc/kim/html/kim_string_overview.html index 765b4d14e..f9e9422f9 100644 --- a/doc/kim/html/kim_string_overview.html +++ b/doc/kim/html/kim_string_overview.html @@ -7,7 +7,7 @@

      KIM String Overview

      A UTF8 string.

      Memory management routines are provided for runtime consistency on operating systems with shared libraries and multiple runtimes.

      -See KIM String Reference Documentation for information on specific APIs.


      Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +See KIM String Reference Documentation for information on specific APIs.
      Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
      diff --git a/doc/kim/html/modules.html b/doc/kim/html/modules.html index fb5fc339b..d0e65fa42 100644 --- a/doc/kim/html/modules.html +++ b/doc/kim/html/modules.html @@ -18,7 +18,7 @@
    • KIM String Reference Documentation
    • KIM Types and Constants
    -
    Generated on Thu Sep 18 10:55:28 2008 for Kerberos Identity Management by  +
    Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  doxygen 1.5.3
    diff --git a/src/include/kim/kim_credential.h b/src/include/kim/kim_credential.h index ed58a72ae..88ccc5dce 100644 --- a/src/include/kim/kim_credential.h +++ b/src/include/kim/kim_credential.h @@ -32,484 +32,532 @@ extern "C" { #include #include - /*! - * \addtogroup kim_types_reference - * @{ - */ - - /*! - * Possible credential states. Credentials may be: - * \li valid - The credential can be used. - * \li expired - The credential's lifetime has been exceeded. - * \li not_yet_valid - The credential is post dated and the time when - * it becomes valid has not yet been reached. - * \li needs_validation - The credential is post-dated and although - * the time when it becomes valid has been reached - * it has not yet been validated. - * \li address_mismatch - The credential contains IP address(es) which do - * not match the host's local address(es). - */ - enum kim_credential_state_enum { - kim_credentials_state_valid = 0, - kim_credentials_state_expired = 1, - kim_credentials_state_not_yet_valid = 2, - kim_credentials_state_needs_validation = 3, - kim_credentials_state_address_mismatch = 4 - }; - - /*! - * The state of a credential. See #kim_credential_state_enum for - * possible values. - */ - typedef int kim_credential_state; - - /*! @} */ - - /*! - * \page kim_credential_overview KIM Credential Overview - * - * \section kim_credential_introduction Introduction - * - * A Kerberos credential (also called a "Kerberos ticket") is a time-limited - * token issued by a KDC which authenticates the entity named by the credential's - * client identity to the service named by the credential's service identity. - * - * The kim_credential object contains a single Kerberos credential. KIM credentials - * objects are always copies of credentials, not references to credentials - * stored in the cache collection. Modifying credential objects in the ccache - * collection will not change any existing KIM credential objects. - * - * KIM credential APIs are intended for applications and system - * tools which manage credentials for the user. They are not a substitute for - * krb5 and GSSAPI functions which obtain service credentials for the purpose - * of authenticating a client to an application server. - * - * \note Many of the APIs listed below have equivalent functions which - * operate on ccaches. In most cases applications will want to use the - * ccache versions of these APIs since they automatically store any - * newly created credentials. See \ref kim_ccache_overview for more - * information. - * - * - * \section kim_credential_acquire_new Acquiring New Credentials - * - * KIM provides the #kim_credential_create_new() API for acquiring new - * credentials. Credentials can either be obtained for a specific - * client identity or by specifying #KIM_IDENTITY_ANY to allow - * the user to choose. Typically callers of this API obtain the client - * identity using #kim_selection_hints_get_identity(). Depending on the - * kim_options specified, #kim_credential_create_new() may present a - * GUI or command line prompt to obtain information from the user. - * - * KIM provides the #kim_credential_create_from_keytab() to create credentials - * using a keytab. A keytab is an on-disk copy of a client identity's secret - * key. Typically sites use keytabs for client identities that identify a - * machine or service and protect the keytab with disk permissions. Because - * a keytab is sufficient to obtain credentials, keytabs will normally only - * be readable by root, Administrator or some other privileged account. - * Typically applications use credentials obtained from keytabs to obtain - * credentials for batch processes. These keytabs and credentials are usually - * for a special identity used for the batch process rather than a user - * identity. - * - * - * \section kim_credential_validate Validating Credentials - * - * A credential with a start time in the future (ie: after the issue date) - * is called a post-dated credential. Because the KDC administrator may - * wish to disable a identity, once the start time is reached, all post-dated - * credentials must be validated before they can be used. Otherwise an - * attacker using a compromised account could acquire lots of post-dated - * credentials to circumvent the acccount being disabled. - * - * KIM provides the #kim_credential_validate() API to validate a credential. - * Note that this API replaces the credential object with a new validated - * credential object. If you wish to store the new credential in the - * ccache collection you must either call #kim_credential_store() on the - * validated credential or use #kim_ccache_validate() instead. - * - * - * \section kim_credential_renew Renewing Credentials - * - * A renewable credential can be used to obtain a new identical credential - * without resending secret information (such as a password) to the KDC. - * A credential may only be renewed during its renewal lifetime and while - * valid. - * - * KIM provides the #kim_credential_renew() API to renew a credential. - * Note that this API replaces the credential object with a new renewed - * credential object. If you wish to store the new credential in the - * ccache collection you must either call #kim_credential_store() on the - * renewed credential or use #kim_ccache_renew() instead. - * - * - * \section kim_credential_storing Storing Credentials in the Cache Collection - * - * KIM credential objects may be stored in the ccache collection using - * #kim_credential_store(). This function runs any KIM authentication - * plugins on the credential and if the plugins return successfully, creates a - * new ccache for the credential's client identity in the cache collection - * and stores the credential in that ccache. Any existing ccaches and credentials - * for that client identity will be overwritten. #kim_credential_store() may - * optionally return a kim_ccache object for the new ccache if you need to perform - * further operations on the new ccache. - * - * Most of the time if you plan to store the credentials you are manipulating, you - * should use one of KIM ccache APIs. These functions perform the same operations - * except that they also call #kim_credential_store() any time the credential object - * changes. See \ref kim_ccache_overview for more information. - * - * - * \section kim_credential_iterator Iterating over the Credentials in a CCache - * - * KIM provides a simple iterator API for iterating over the credentials - * in a ccache. First, call #kim_credential_iterator_create() to obtain - * an iterator for a ccache. Then loop calling #kim_credential_iterator_next() - * until either you find the credential you are looking for or the API - * returns a NULL credential, indicating that there are no more - * credentials in the ccache. When you are done with the iterator, call - * #kim_credential_iterator_free(). - * - * \note #kim_credential_iterator_next() returns credential objects which - * must be freed with #kim_credential_free() to avoid leaking memory. - * - * - * \section kim_credential_verify Verifying Credentials - * - * When a program acquires TGT credentials for the purpose of authenticating - * itself to the machine it is running on, it is insufficient for the machine - * to assume that the caller is authorized just because it got credentials. - * Instead, the credentials must be verified using a key the local machine. - * The reason this is necessary is because an attacker can trick the - * machine into obtaining credentials from any KDC, including malicious ones - * with the same realm name as the local machine's realm. This exploit is - * called the Zanarotti attack. - * - * In order to avoid the Zanarotti attack, the local machine must authenticate - * the process in the same way an application server would authenticate a client. - * Like an application server, the local machine must have its own identity in - * its realm and a keytab for that identity on its local disk. However, - * rather than forcing system daemons to use the network-oriented calls in the - * krb5 and GSS APIs, KIM provides the #kim_credential_verify() API to - * verify credentials directly. - * - * The most common reason for using #kim_credential_verify() is user login. - * If the local machine wants to use Kerberos to verify the username and password - * provided by the user, it must call #kim_credential_verify() on the credentials - * it obtains to make sure they are really from a KDC it trusts. Another common - * case is a server which is only using Kerberos internally. For example an - * LDAP or web server might use a username and password obtained over the network - * to get Kerberos credentials. In order to make sure they aren't being tricked - * into talking to the wrong KDC, these servers must also call - * #kim_credential_verify(). - * - * The Zanarotti attack is only a concern if the act of accessing the machine - * gives the process special access. Thus a managed cluster machine with - * Kerberos-authenticated networked home directories does not need to call - * #kim_credential_verify(). Even though an attacker can log in as any user on - * the cluster machine, the attacker can't actually access any of the user's data - * or use any of their privileges because those are all authenticated via - * Kerberized application servers (and thus require actually having credentials - * for the real local realm). - * - * #kim_credential_verify() provides an option to - * return success even if the machine's host key is not present. This option - * exists for sites which have a mix of different machines, some of which are - * vulnerable to the Zanarotti attack and some are not. If this option is used, - * it is the responsiblity of the machine's maintainer to obtain a keytab - * for their machine if it needs one. - * - * - * \section kim_credential_properties Examining Credential Properties - * - * \li #kim_credential_get_client_identity() - * returns the credential's client identity. - * - * \li #kim_credential_get_service_identity() - * returns the credential's service identity. - * - * \li #kim_credential_is_tgt() - * returns whether the credential is a TGT (ie: "ticket-granting ticket"). TGTs are - * credentials for the krbtgt service: a service identity of the form "krbtgt/@". - * These credentials allow the entity named by the client identity to obtain - * additional service credentials without resending shared secrets (such as a password) - * to the KDC. Kerberos uses TGTs to provide single sign-on authentication. - * - * \li #kim_credential_is_valid() - * returns whether the credential is valid and if not why the credential is not valid. - * - * \li #kim_credential_get_start_time() - * returns when the credential will become valid. - * Credentials may be "post-dated" which means that their lifetime starts sometime - * in the future. Note that when a post-dated credential's start time is reached, - * the credential must be validated. See \ref kim_credential_validate for more information. - * - * \li #kim_credential_get_expiration_time() - * returns when the credential will expire. - * Credentials are time limited by the lifetime of the credential. While you can - * request a credential of any lifetime, the KDC limits the credential lifetime - * to a administrator-defined maximum. Typically credential lifetime range from 10 - * to 21 hours. - * - * \li #kim_credential_get_renewal_expiration_time() - * returns when the credential will no longer be renewable. - * Valid credentials may be renewed up until their renewal expiration time. - * Renewing credentials acquires a fresh set of credentials with a full lifetime - * without resending secrets to the KDC (such as a password). If credentials are - * not renewable, this function will return an error. - * - * - * See \ref kim_credential_reference and \ref kim_credential_iterator_reference for - * information on specific APIs. - */ - - /*! - * \defgroup kim_credential_iterator_reference KIM Credential Iterator Reference Documentation - * @{ - */ - - /*! - * \param out_credential_iterator on exit, a credential iterator object for \a in_ccache. - * Must be freed with kim_credential_iterator_free(). - * \param in_ccache a ccache object. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get a credential iterator to enumerate credentials in a ccache. - */ - - kim_error kim_credential_iterator_create (kim_credential_iterator *out_credential_iterator, - kim_ccache in_ccache); - - /*! - * \param in_credential_iterator a credential iterator object. - * \param out_credential on exit, the next credential in the ccache iterated by - * \a in_credential_iterator. Must be freed with - * kim_credential_free(). If there are no more credentials - * this argument will be set to NULL. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the next credential in a ccache. - */ - - kim_error kim_credential_iterator_next (kim_credential_iterator in_credential_iterator, - kim_credential *out_credential); - - /*! - * \param io_credential_iterator a credential iterator object to be freed. Set to NULL on exit. - * \brief Free memory associated with a credential iterator. - */ - void kim_credential_iterator_free (kim_credential_iterator *io_credential_iterator); - - /*!@}*/ - - /*! - * \defgroup kim_credential_reference KIM Credential Reference Documentation - * @{ - */ - - /*! - * \param out_credential on exit, a new credential object containing a newly acquired - * initial credential. Must be freed with kim_credential_free(). - * \param in_client_identity a client identity to obtain a credential for. Specify NULL to - * allow the user to choose the identity - * \param in_options options to control credential acquisition. - * \note Depending on the kim_options specified, #kim_credential_create_new() may - * present a GUI or command line prompt to obtain information from the user. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Acquire a new initial credential. - * \sa kim_ccache_create_new - */ - kim_error kim_credential_create_new (kim_credential *out_credential, - kim_identity in_client_identity, - kim_options in_options); - - /*! - * \param out_credential on exit, a new credential object containing an initial credential - * for \a in_identity obtained using \a in_keytab. - * Must be freed with kim_credential_free(). - * \param in_identity a client identity to obtain a credential for. Specify NULL for - * the first identity in the keytab. - * \param in_options options to control credential acquisition. - * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Acquire a new initial credential from a keytab. - * \sa kim_ccache_create_from_keytab - */ - kim_error kim_credential_create_from_keytab (kim_credential *out_credential, - kim_identity in_identity, - kim_options in_options, - kim_string in_keytab); - - /*! - * \param out_credential on exit, a new credential object which is a copy of \a in_krb5_creds. - * Must be freed with kim_credential_free(). - * \param in_krb5_context the krb5 context used to create \a in_krb5_creds. - * \param in_krb5_creds a krb5 credential object. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Copy a credential from a krb5 credential object. - */ - kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, - krb5_context in_krb5_context, - krb5_creds *in_krb5_creds); - - /*! - * \param out_credential on exit, a new credential object which is a copy of \a in_credential. - * Must be freed with kim_credential_free(). - * \param in_credential a credential object. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Copy a credential object. - */ - kim_error kim_credential_copy (kim_credential *out_credential, - kim_credential in_credential); - - /*! - * \param in_credential a credential object. - * \param in_krb5_context a krb5 context which will be used to create \a out_krb5_creds. - * \param out_krb5_creds on exit, a new krb5 creds object which is a copy of \a in_credential. - * Must be freed with krb5_free_creds(). - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get a krb5 credentials object for a credential object. - */ - kim_error kim_credential_get_krb5_creds (kim_credential in_credential, - krb5_context in_krb5_context, - krb5_creds **out_krb5_creds); - - /*! - * \param in_credential a credential object. - * \param out_client_identity on exit, an identity object containing the client identity of - * \a in_credential. Must be freed with kim_identity_free(). - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the client identity of a credential object. - */ - kim_error kim_credential_get_client_identity (kim_credential in_credential, - kim_identity *out_client_identity); - - /*! - * \param in_credential a credential object. - * \param out_service_identity on exit, an identity object containing the service identity of - * \a in_credential. Must be freed with kim_identity_free(). - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the service identity of a credential object. - */ - kim_error kim_credential_get_service_identity (kim_credential in_credential, - kim_identity *out_service_identity); - - /*! - * \param in_credential a credential object. - * \param out_is_tgt on exit, whether or not the credential is a TGT. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Check if a credential is a ticket granting ticket. - */ - kim_error kim_credential_is_tgt (kim_credential in_credential, - kim_boolean *out_is_tgt); - - /*! - * \param in_credential a credential object. - * \param out_state on exit, the state of the credential. See #kim_credential_state_enum - * for the possible values of \a out_state. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Check the state of a credential (valid, expired, postdated, etc). - */ - kim_error kim_credential_get_state (kim_credential in_credential, - kim_credential_state *out_state); - - /*! - * \param in_credential a credential object. - * \param out_start_time on exit, the time when \a in_credential becomes valid. - * May be in the past or future. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the time when the credentials become valid. - * \sa kim_ccache_get_start_time - */ - kim_error kim_credential_get_start_time (kim_credential in_credential, - kim_time *out_start_time); - - /*! - * \param in_credential a credential object. - * \param out_expiration_time on exit, the time when \a in_credential will expire. - * May be in the past or future. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the time when the credentials will expire. - * \sa kim_ccache_get_expiration_time - */ - kim_error kim_credential_get_expiration_time (kim_credential in_credential, - kim_time *out_expiration_time); - - /*! - * \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. - * \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 - */ - 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 in_client_identity a client identity. - * \param out_ccache on exit, a ccache object containing \a in_credential with the client - * identity \a in_client_identity. Must be freed with kim_ccache_free(). - * Specify NULL if you don't want this return value. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Store a credential in a ccache in the cache collection. - */ - kim_error kim_credential_store (kim_credential in_credential, - kim_identity in_client_identity, - kim_ccache *out_ccache); - - /*! - * \param in_credential a TGT credential to be verified. - * \param in_service_identity a service identity to look for in the keytab. Specify - * KIM_IDENTITY_ANY to use the default service identity - * (usually host/@). - * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. - * \param in_fail_if_no_service_key whether or not the absence of a key for \a in_service_identity - * in the host's keytab will cause a failure. - * \note specifying FALSE for \a in_fail_if_no_service_key may expose the calling program to - * the Zanarotti attack if the host has no keytab installed. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Verify a TGT credential. - * \sa kim_ccache_verify - */ - kim_error kim_credential_verify (kim_credential in_credential, - kim_identity in_service_identity, - kim_string in_keytab, - kim_boolean in_fail_if_no_service_key); - - /*! - * \param io_credential a TGT credential to be renewed. On exit, the old credential - * object will be freed and \a io_credential will be replaced - * with a new renewed credential. The new credential must be freed - * with kim_credential_free(). - * \param in_options initial credential options. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Renew a TGT credential. - * \sa kim_ccache_renew - */ - kim_error kim_credential_renew (kim_credential *io_credential, - kim_options in_options); - - /*! - * \param io_credential a credential object to be validated. On exit, the old credential - * object will be freed and \a io_credential will be replaced - * with a new validated credential. The new credential must be freed - * with kim_credential_free(). - * \param in_options initial credential options. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Validate a TGT credential. - * \sa kim_ccache_validate - */ - kim_error kim_credential_validate (kim_credential *io_credential, - kim_options in_options); - - /*! - * \param io_credential the credential object to be freed. Set to NULL on exit. - * \brief Free memory associated with a credential object. - */ - void kim_credential_free (kim_credential *io_credential); - - /*!@}*/ +/*! + * \addtogroup kim_types_reference + * @{ + */ + +/*! + * Possible credential states. Credentials may be: + * \li valid - The credential can be used. + * \li expired - The credential's lifetime has been exceeded. + * \li not_yet_valid - The credential is post dated and the time when + * it becomes valid has not yet been reached. + * \li needs_validation - The credential is post-dated and although + * the time when it becomes valid has been reached + * it has not yet been validated. + * \li address_mismatch - The credential contains IP address(es) which do + * not match the host's local address(es). + */ +enum kim_credential_state_enum { + kim_credentials_state_valid = 0, + kim_credentials_state_expired = 1, + kim_credentials_state_not_yet_valid = 2, + kim_credentials_state_needs_validation = 3, + kim_credentials_state_address_mismatch = 4 +}; + +/*! + * The state of a credential. See #kim_credential_state_enum for + * possible values. + */ +typedef int kim_credential_state; + +/*! @} */ + +/*! + * \page kim_credential_overview KIM Credential Overview + * + * \section kim_credential_introduction Introduction + * + * A Kerberos credential (also called a "Kerberos ticket") is a time-limited + * token issued by a KDC which authenticates the entity named by the credential's + * client identity to the service named by the credential's service identity. + * + * The kim_credential object contains a single Kerberos credential. KIM credentials + * objects are always copies of credentials, not references to credentials + * stored in the cache collection. Modifying credential objects in the ccache + * collection will not change any existing KIM credential objects. + * + * KIM credential APIs are intended for applications and system + * tools which manage credentials for the user. They are not a substitute for + * krb5 and GSSAPI functions which obtain service credentials for the purpose + * of authenticating a client to an application server. + * + * \note Many of the APIs listed below have equivalent functions which + * operate on ccaches. In most cases applications will want to use the + * ccache versions of these APIs since they automatically store any + * newly created credentials. See \ref kim_ccache_overview for more + * information. + * + * + * \section kim_credential_acquire_new Acquiring New Credentials + * + * KIM provides the #kim_credential_create_new() API for acquiring new + * credentials. Credentials can either be obtained for a specific + * client identity or by specifying #KIM_IDENTITY_ANY to allow + * the user to choose. Typically callers of this API obtain the client + * identity using #kim_selection_hints_get_identity(). Depending on the + * kim_options specified, #kim_credential_create_new() may present a + * GUI or command line prompt to obtain information from the user. + * + * KIM provides the #kim_credential_create_from_keytab() to create credentials + * using a keytab. A keytab is an on-disk copy of a client identity's secret + * key. Typically sites use keytabs for client identities that identify a + * machine or service and protect the keytab with disk permissions. Because + * a keytab is sufficient to obtain credentials, keytabs will normally only + * be readable by root, Administrator or some other privileged account. + * Typically applications use credentials obtained from keytabs to obtain + * credentials for batch processes. These keytabs and credentials are usually + * for a special identity used for the batch process rather than a user + * identity. + * + * + * \section kim_credential_validate Validating Credentials + * + * A credential with a start time in the future (ie: after the issue date) + * is called a post-dated credential. Because the KDC administrator may + * wish to disable a identity, once the start time is reached, all post-dated + * credentials must be validated before they can be used. Otherwise an + * attacker using a compromised account could acquire lots of post-dated + * credentials to circumvent the acccount being disabled. + * + * KIM provides the #kim_credential_validate() API to validate a credential. + * Note that this API replaces the credential object with a new validated + * credential object. If you wish to store the new credential in the + * ccache collection you must either call #kim_credential_store() on the + * validated credential or use #kim_ccache_validate() instead. + * + * + * \section kim_credential_renew Renewing Credentials + * + * A renewable credential can be used to obtain a new identical credential + * without resending secret information (such as a password) to the KDC. + * A credential may only be renewed during its renewal lifetime and while + * valid. + * + * KIM provides the #kim_credential_renew() API to renew a credential. + * Note that this API replaces the credential object with a new renewed + * credential object. If you wish to store the new credential in the + * ccache collection you must either call #kim_credential_store() on the + * renewed credential or use #kim_ccache_renew() instead. + * + * + * \section kim_credential_storing Storing Credentials in the Cache Collection + * + * KIM credential objects may be stored in the ccache collection using + * #kim_credential_store(). This function runs any KIM authentication + * plugins on the credential and if the plugins return successfully, creates a + * new ccache for the credential's client identity in the cache collection + * and stores the credential in that ccache. Any existing ccaches and credentials + * for that client identity will be overwritten. #kim_credential_store() may + * optionally return a kim_ccache object for the new ccache if you need to perform + * further operations on the new ccache. + * + * Most of the time if you plan to store the credentials you are manipulating, you + * should use one of KIM ccache APIs. These functions perform the same operations + * except that they also call #kim_credential_store() any time the credential object + * changes. See \ref kim_ccache_overview for more information. + * + * + * \section kim_credential_iterator Iterating over the Credentials in a CCache + * + * KIM provides a simple iterator API for iterating over the credentials + * in a ccache. First, call #kim_credential_iterator_create() to obtain + * an iterator for a ccache. Then loop calling #kim_credential_iterator_next() + * until either you find the credential you are looking for or the API + * returns a NULL credential, indicating that there are no more + * credentials in the ccache. When you are done with the iterator, call + * #kim_credential_iterator_free(). + * + * \note #kim_credential_iterator_next() returns credential objects which + * must be freed with #kim_credential_free() to avoid leaking memory. + * + * + * \section kim_credential_verify Verifying Credentials + * + * When a program acquires TGT credentials for the purpose of authenticating + * itself to the machine it is running on, it is insufficient for the machine + * to assume that the caller is authorized just because it got credentials. + * Instead, the credentials must be verified using a key the local machine. + * The reason this is necessary is because an attacker can trick the + * machine into obtaining credentials from any KDC, including malicious ones + * with the same realm name as the local machine's realm. This exploit is + * called the Zanarotti attack. + * + * In order to avoid the Zanarotti attack, the local machine must authenticate + * the process in the same way an application server would authenticate a client. + * Like an application server, the local machine must have its own identity in + * its realm and a keytab for that identity on its local disk. However, + * rather than forcing system daemons to use the network-oriented calls in the + * krb5 and GSS APIs, KIM provides the #kim_credential_verify() API to + * verify credentials directly. + * + * The most common reason for using #kim_credential_verify() is user login. + * If the local machine wants to use Kerberos to verify the username and password + * provided by the user, it must call #kim_credential_verify() on the credentials + * it obtains to make sure they are really from a KDC it trusts. Another common + * case is a server which is only using Kerberos internally. For example an + * LDAP or web server might use a username and password obtained over the network + * to get Kerberos credentials. In order to make sure they aren't being tricked + * into talking to the wrong KDC, these servers must also call + * #kim_credential_verify(). + * + * The Zanarotti attack is only a concern if the act of accessing the machine + * gives the process special access. Thus a managed cluster machine with + * Kerberos-authenticated networked home directories does not need to call + * #kim_credential_verify(). Even though an attacker can log in as any user on + * the cluster machine, the attacker can't actually access any of the user's data + * or use any of their privileges because those are all authenticated via + * Kerberized application servers (and thus require actually having credentials + * for the real local realm). + * + * #kim_credential_verify() provides an option to + * return success even if the machine's host key is not present. This option + * exists for sites which have a mix of different machines, some of which are + * vulnerable to the Zanarotti attack and some are not. If this option is used, + * it is the responsiblity of the machine's maintainer to obtain a keytab + * for their machine if it needs one. + * + * + * \section kim_credential_properties Examining Credential Properties + * + * \li #kim_credential_get_client_identity() + * returns the credential's client identity. + * + * \li #kim_credential_get_service_identity() + * returns the credential's service identity. + * + * \li #kim_credential_is_tgt() + * returns whether the credential is a TGT (ie: "ticket-granting ticket"). TGTs are + * credentials for the krbtgt service: a service identity of the form "krbtgt/@". + * These credentials allow the entity named by the client identity to obtain + * additional service credentials without resending shared secrets (such as a password) + * to the KDC. Kerberos uses TGTs to provide single sign-on authentication. + * + * \li #kim_credential_is_valid() + * returns whether the credential is valid and if not why the credential is not valid. + * + * \li #kim_credential_get_start_time() + * returns when the credential will become valid. + * Credentials may be "post-dated" which means that their lifetime starts sometime + * in the future. Note that when a post-dated credential's start time is reached, + * the credential must be validated. See \ref kim_credential_validate for more information. + * + * \li #kim_credential_get_expiration_time() + * returns when the credential will expire. + * Credentials are time limited by the lifetime of the credential. While you can + * request a credential of any lifetime, the KDC limits the credential lifetime + * to a administrator-defined maximum. Typically credential lifetime range from 10 + * to 21 hours. + * + * \li #kim_credential_get_renewal_expiration_time() + * returns when the credential will no longer be renewable. + * Valid credentials may be renewed up until their renewal expiration time. + * Renewing credentials acquires a fresh set of credentials with a full lifetime + * without resending secrets to the KDC (such as a password). If credentials are + * not renewable, this function will return an error. + * + * + * See \ref kim_credential_reference and \ref kim_credential_iterator_reference for + * information on specific APIs. + */ + +/*! + * \defgroup kim_credential_iterator_reference KIM Credential Iterator Reference Documentation + * @{ + */ + +/*! + * \param out_credential_iterator on exit, a credential iterator object for \a in_ccache. + * Must be freed with kim_credential_iterator_free(). + * \param in_ccache a ccache object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a credential iterator to enumerate credentials in a ccache. + */ + +kim_error kim_credential_iterator_create (kim_credential_iterator *out_credential_iterator, + kim_ccache in_ccache); + +/*! + * \param in_credential_iterator a credential iterator object. + * \param out_credential on exit, the next credential in the ccache iterated by + * \a in_credential_iterator. Must be freed with + * kim_credential_free(). If there are no more credentials + * this argument will be set to NULL. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the next credential in a ccache. + */ + +kim_error kim_credential_iterator_next (kim_credential_iterator in_credential_iterator, + kim_credential *out_credential); + +/*! + * \param io_credential_iterator a credential iterator object to be freed. Set to NULL on exit. + * \brief Free memory associated with a credential iterator. + */ +void kim_credential_iterator_free (kim_credential_iterator *io_credential_iterator); + +/*!@}*/ + +/*! + * \defgroup kim_credential_reference KIM Credential Reference Documentation + * @{ + */ + +/*! + * \param out_credential on exit, a new credential object containing a newly acquired + * initial credential. Must be freed with kim_credential_free(). + * \param in_client_identity a client identity to obtain a credential for. Specify NULL to + * allow the user to choose the identity + * \param in_options options to control credential acquisition. + * \note Depending on the kim_options specified, #kim_credential_create_new() may + * present a GUI or command line prompt to obtain information from the user. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential. + * \sa kim_ccache_create_new + */ +kim_error kim_credential_create_new (kim_credential *out_credential, + kim_identity in_client_identity, + kim_options in_options); + +/*! + * \param out_credential on exit, a new credential object containing an initial credential + * for \a in_identity obtained using \a in_keytab. + * Must be freed with kim_credential_free(). + * \param in_identity a client identity to obtain a credential for. Specify NULL for + * the first identity in the keytab. + * \param in_options options to control credential acquisition. + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential from a keytab. + * \sa kim_ccache_create_from_keytab + */ +kim_error kim_credential_create_from_keytab (kim_credential *out_credential, + kim_identity in_identity, + kim_options in_options, + kim_string in_keytab); + +/*! + * \param out_credential on exit, a new credential object which is a copy of \a in_krb5_creds. + * Must be freed with kim_credential_free(). + * \param in_krb5_context the krb5 context used to create \a in_krb5_creds. + * \param in_krb5_creds a krb5 credential object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a credential from a krb5 credential object. + */ +kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, + krb5_context in_krb5_context, + krb5_creds *in_krb5_creds); + +/*! + * \param out_credential on exit, a new credential object containing a change + * password credential for \a in_identity. + * Must be freed with kim_credential_free(). + * \param in_identity a client identity to obtain a change password credential for. + * \param in_old_password the current password for \a in_identity. May be + * an expired password. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Obtain a credential for changing an identity's password. + * \sa kim_credential_change_password + */ +kim_error kim_credential_create_for_change_password (kim_credential *out_credential, + kim_identity in_identity, + kim_string in_old_password); + +/*! + * \param out_credential on exit, a new credential object which is a copy of \a in_credential. + * Must be freed with kim_credential_free(). + * \param in_credential a credential object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a credential object. + */ +kim_error kim_credential_copy (kim_credential *out_credential, + kim_credential in_credential); + +/*! + * \param in_credential a credential object. + * \param in_krb5_context a krb5 context which will be used to create \a out_krb5_creds. + * \param out_krb5_creds on exit, a new krb5 creds object which is a copy of \a in_credential. + * Must be freed with krb5_free_creds(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a krb5 credentials object for a credential object. + */ +kim_error kim_credential_get_krb5_creds (kim_credential in_credential, + krb5_context in_krb5_context, + krb5_creds **out_krb5_creds); + +/*! + * \param in_credential a credential object. + * \param out_client_identity on exit, an identity object containing the client identity of + * \a in_credential. Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the client identity of a credential object. + */ +kim_error kim_credential_get_client_identity (kim_credential in_credential, + kim_identity *out_client_identity); + +/*! + * \param in_credential a credential object. + * \param out_service_identity on exit, an identity object containing the service identity of + * \a in_credential. Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the service identity of a credential object. + */ +kim_error kim_credential_get_service_identity (kim_credential in_credential, + kim_identity *out_service_identity); + +/*! + * \param in_credential a credential object. + * \param out_is_tgt on exit, whether or not the credential is a TGT. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Check if a credential is a ticket granting ticket. + */ +kim_error kim_credential_is_tgt (kim_credential in_credential, + kim_boolean *out_is_tgt); + +/*! + * \param in_credential a credential object. + * \param out_state on exit, the state of the credential. See #kim_credential_state_enum + * for the possible values of \a out_state. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Check the state of a credential (valid, expired, postdated, etc). + */ +kim_error kim_credential_get_state (kim_credential in_credential, + kim_credential_state *out_state); + +/*! + * \param in_credential a credential object. + * \param out_start_time on exit, the time when \a in_credential becomes valid. + * May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials become valid. + * \sa kim_ccache_get_start_time + */ +kim_error kim_credential_get_start_time (kim_credential in_credential, + kim_time *out_start_time); + +/*! + * \param in_credential a credential object. + * \param out_expiration_time on exit, the time when \a in_credential will expire. + * May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials will expire. + * \sa kim_ccache_get_expiration_time + */ +kim_error kim_credential_get_expiration_time (kim_credential in_credential, + kim_time *out_expiration_time); + +/*! + * \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. + * \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 + */ +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 in_client_identity a client identity. + * \param out_ccache on exit, a ccache object containing \a in_credential with the client + * identity \a in_client_identity. Must be freed with kim_ccache_free(). + * Specify NULL if you don't want this return value. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Store a credential in a ccache in the cache collection. + */ +kim_error kim_credential_store (kim_credential in_credential, + kim_identity in_client_identity, + kim_ccache *out_ccache); + +/*! + * \param in_credential a TGT credential to be verified. + * \param in_service_identity a service identity to look for in the keytab. Specify + * KIM_IDENTITY_ANY to use the default service identity + * (usually host/@). + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \param in_fail_if_no_service_key whether or not the absence of a key for \a in_service_identity + * in the host's keytab will cause a failure. + * \note specifying FALSE for \a in_fail_if_no_service_key may expose the calling program to + * the Zanarotti attack if the host has no keytab installed. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Verify a TGT credential. + * \sa kim_ccache_verify + */ +kim_error kim_credential_verify (kim_credential in_credential, + kim_identity in_service_identity, + kim_string in_keytab, + kim_boolean in_fail_if_no_service_key); + +/*! + * \param io_credential a TGT credential to be renewed. On exit, the old credential + * object will be freed and \a io_credential will be replaced + * with a new renewed credential. The new credential must be freed + * with kim_credential_free(). + * \param in_options initial credential options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Renew a TGT credential. + * \sa kim_ccache_renew + */ +kim_error kim_credential_renew (kim_credential *io_credential, + kim_options in_options); + +/*! + * \param io_credential a credential object to be validated. On exit, the old credential + * object will be freed and \a io_credential will be replaced + * with a new validated credential. The new credential must be freed + * with kim_credential_free(). + * \param in_options initial credential options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Validate a TGT credential. + * \sa kim_ccache_validate + */ +kim_error kim_credential_validate (kim_credential *io_credential, + kim_options in_options); + +/*! + * \param in_credential a credential object containing a change + * password credential. Use + * #kim_credential_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 + * is for. + * \param in_new_password the password to change the identity to. + * \param out_rejected_err on exit, 0 if the password change was + * successful or an error describing why the + * new password was rejected. + * \param out_rejected_message on exit, if \a out_rejected_err is non-zero + * this argument will contain an error message + * for \a out_rejected_err. Pass NULL if you + * do not want this error string. Must be + * freed with #kim_string_free(); + * \param out_rejected_description on exit, if \a out_rejected_err is non-zero + * this argument will contain an string describing + * why \a in_new_password was rejected. Pass NULL + * if you do not want this error string. Must be + * freed with #kim_string_free(); + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Change an identity's password. + * \sa kim_credential_create_for_change_password + */ +kim_error kim_credential_change_password (kim_credential in_credential, + kim_identity in_identity, + kim_string in_new_password, + kim_error *out_rejected_err, + kim_string *out_rejected_message, + kim_string *out_rejected_description); + +/*! + * \param io_credential the credential object to be freed. Set to NULL on exit. + * \brief Free memory associated with a credential object. + */ +void kim_credential_free (kim_credential *io_credential); + +/*!@}*/ #ifdef __cplusplus diff --git a/src/include/kim/kim_identity.h b/src/include/kim/kim_identity.h index 4461c3163..f09c24aa7 100644 --- a/src/include/kim/kim_identity.h +++ b/src/include/kim/kim_identity.h @@ -256,29 +256,12 @@ kim_error kim_identity_get_krb5_principal (kim_identity in_identity, /*! * \param in_identity an identity object whose password will be changed. - * \param in_options initial credential options to be used if a new credential is obtained. * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. * \brief Change the password for an identity. * \note kim_identity_change_password() will acquire a temporary credential to change - * the password. It uses the \a in_options structure to obtain information about the desired - * prompter and current password. + * the password. */ -kim_error kim_identity_change_password (kim_identity in_identity, - kim_options in_options); - -/*! - * \param in_identity an identity object whose password will be changed. - * \param in_options initial credential options to be used if a new credential is obtained. - * \param in_new_password a string representation of the identity's new password. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Change the password for an identity to a caller-provided new password. - * \note kim_identity_change_password_with_passwords() will acquire a temporary credential - * to change the password. It uses the \a in_options structure to obtain information about - * the desired prompter and current password. - */ -kim_error kim_identity_change_password_to_password (kim_identity in_identity, - kim_options in_options, - kim_string in_new_password); +kim_error kim_identity_change_password (kim_identity in_identity); /*! * \param io_identity the identity object to be freed. Set to NULL on exit. diff --git a/src/include/kim/kim_options.h b/src/include/kim/kim_options.h index f5b975cf3..2c82b3ef5 100644 --- a/src/include/kim/kim_options.h +++ b/src/include/kim/kim_options.h @@ -46,70 +46,6 @@ extern "C" { */ #define KIM_OPTIONS_START_IMMEDIATELY ((kim_time_t) 0) -/*! - * The type of prompt which needs to be displayed. - * This value determines what type of user interface is displayed. - * See \ref kim_options_custom_prompt_callback for more information. - */ -typedef uint32_t kim_prompt_type; - -enum kim_prompt_type_enum { - kim_prompt_type_password = 0, - kim_prompt_type_challenge = 1 -}; - -/*! - * The prompt callback used to display a prompt to the user. - * See \ref kim_options_custom_prompt_callback for more information. - */ -typedef kim_error (*kim_prompt_callback) (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply); - -/*! - * The default prompt callback. - * See \ref kim_options_custom_prompt_callback for more information. - */ -kim_error kim_prompt_callback_default (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply); - -/*! - * The graphical prompt callback. - * See \ref kim_options_custom_prompt_callback for more information. - */ -kim_error kim_prompt_callback_gui (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply); - -/*! - * The command line prompt callback. - * See \ref kim_options_custom_prompt_callback for more information. - */ -kim_error kim_prompt_callback_cli (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply); - -/*! - * The prompt callback which always returns an error. - * Use to turn off prompting entirely. - * \note Using this callback may prevent the user from authenicating. - * See \ref kim_options_custom_prompt_callback for more information. - */ -kim_error kim_prompt_callback_none (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply); - /*! @} */ /*! @@ -126,34 +62,6 @@ kim_error kim_prompt_callback_none (kim_prompt_type in_type, * KIM options fall into two major categories: options for controlling how credentials are * acquired and options for controlling what properties the newly acquired credentials will have: * - * \section kim_options_credential_acquisition Options for Controlling Credential Acquisition - * - * In order to acquire credentials, Kerberos needs to obtain one or more secrets from the user. - * These secrets may be a certificate, password, SecurID pin, or information from a smart card. - * If obtaining the secret requires interaction with the user, the Kerberos libraries call a - * "prompter callback" to display a dialog or command line prompt to request information from - * the user. If you want to provide your own custom dialogs or command line prompts, - * the KIM APIs provide a mechanism for replacing the default prompt callbacks with your own. - * - * \subsection kim_options_custom_prompt_callback Providing a Custom Prompt Callback - * - * All secrets are obtained from the user through a #kim_prompt_callback_t. By default, - * options use #kim_prompt_callback_default, which presents a dialog to request - * information from the user, or if no graphical access is available, a command line prompt. - * - * KIM also provides three other callbacks: #kim_prompt_callback_gui only presents - * a dialog and returns an error if there is no graphical access. #kim_prompt_callback_cli - * only presents a command line interface and returns an error if there is no controlling - * terminal available. #kim_prompt_callback_none always returns an error. - * - * Using #kim_options_set_prompt_callback(), you can change the prompt callback to one of - * the above callbacks or a callback you have defined yourself. Callbacks are called in a - * loop, one for each prompt. Because network traffic may occur between calls to the prompt - * callback, your prompt interface should support time passing between calls to the prompter. - * If you are defining a callback yourself, you should also set your own options data with - * #kim_options_set_data() for storing state between calls. Options data is a caller - * defined pointer value -- the Kerberos libaries make no use of it. - * * \section kim_options_credential_properties Options for Controlling Credential Properties * * Kerberos credentials have a number of different properties which can be requested @@ -285,61 +193,6 @@ kim_error kim_options_create (kim_options *out_options); kim_error kim_options_copy (kim_options *out_options, kim_options in_options); -/*! - * \param io_options an options object to modify. - * \param in_prompt_callback a prompt callback function. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Set the prompt callback for obtaining information from the user. - * \par Default value - * #kim_prompt_callback_default - * \sa kim_options_get_prompt_callback() - */ -kim_error kim_options_set_prompt_callback (kim_options io_options, - kim_prompt_callback in_prompt_callback); - -/*! - * \param in_options an options object. - * \param out_prompt_callback on exit, the prompt callback specified by in_options. - * Does not need to be freed but may become invalid when - * \a in_options is freed. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the prompt callback for obtaining information from the user. - * \par Default value - * #kim_prompt_callback_default - * \sa kim_options_set_prompt_callback() - */ -kim_error kim_options_get_prompt_callback (kim_options in_options, - kim_prompt_callback *out_prompt_callback); - -/*! - * \param io_options an options object to modify. - * \param in_data a pointer to caller-specific data. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Set caller-specific data for use in library callbacks. - * \note This option can be used by the caller to store a pointer to data needed when handling a - * callback. The KIM library does not use this options data in any way. - * \par Default value - * NULL (no data is set by default) - * \sa kim_options_get_data() - */ -kim_error kim_options_set_data (kim_options io_options, - const void *in_data); - -/*! - * \param in_options an options object. - * \param out_data on exit, the pointer to caller specific data specified by in_options. - * Does not need to be freed but may become invalid when \a in_options is freed. - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get caller-specific data for use in library callbacks. - * \note This option can be used by the caller to store a pointer to data needed when handling a - * callback. The KIM library does not use this options data in any way. - * \par Default value - * NULL (no data is set by default) - * \sa kim_options_set_data() - */ -kim_error kim_options_get_data (kim_options in_options, - const void **out_data); - /*! * \param io_options an options object to modify. * \param in_start_time a start date (in seconds since January 1, 1970). Set to diff --git a/src/include/kim/kim_ui_plugin.h b/src/include/kim/kim_ui_plugin.h index d7fd6e1b7..b7d48ad89 100644 --- a/src/include/kim/kim_ui_plugin.h +++ b/src/include/kim/kim_ui_plugin.h @@ -29,7 +29,28 @@ extern "C" { #endif +/*! + * The type of prompt which needs to be displayed. + * This value determines what type of user interface is displayed. + * See \ref kim_options_custom_prompt_callback for more information. + */ +typedef uint32_t kim_prompt_type; + +enum kim_prompt_type_enum { + kim_prompt_type_password = 0, + kim_prompt_type_preauth = 1 +}; + /* + * Plugins for Controlling Identity Selection and Credential Acquisition + * + * In order to acquire credentials, Kerberos needs to obtain one or more secrets from the user. + * These secrets may be a certificate, password, SecurID pin, or information from a smart card. + * If obtaining the secret requires interaction with the user, the Kerberos libraries call a + * "prompter callback" to display a dialog or command line prompt to request information from + * the user. If you want to provide your own custom dialogs or command line prompts, + * the KIM APIs provide a plugin mechanism for replacing the default prompt ui with your own. + * * The function table / structure which a KIM ui plugin module must export * as "kim_ui_0". If the interfaces work correctly, future versions of the * table will add either more callbacks or more arguments to callbacks, and @@ -49,9 +70,19 @@ typedef struct kim_ui_plugin_ftable_v0 { * this ui. */ kim_error (*init) (void **out_context); + /* Present UI which allows the user to enter a new identity. + * This is typically called when the user selects a "new tickets" + * control or menu item from a ticket management utility. + * If this UI calls into KIM to get new credentials it may + * call auth_prompt below. */ + kim_error (*enter_identity) (void *in_context, + kim_identity *out_identity); + /* Present UI to select which identity to use. + * This is typically called the first time an application tries to use + * Kerberos and is used to establish a hints preference for the application. * If this UI calls into KIM to get new credentials it may - * call acquire_new_credentials below. */ + * call auth_prompt below. */ kim_error (*select_identity) (void *in_context, kim_selection_hints in_hints, kim_identity *out_identity); @@ -60,13 +91,14 @@ typedef struct kim_ui_plugin_ftable_v0 { kim_error (*auth_prompt) (void *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); /* Prompt to change the identity's password. - * May be combined with an auth prompt if additional auth is required, + * May be combined with an auth_prompt if additional auth is required, * eg: SecurID pin. * If in_old_password_expired is true, this callback is in response * to an expired password error. If this is the case the same context @@ -79,15 +111,18 @@ typedef struct kim_ui_plugin_ftable_v0 { char **out_verify_password); /* Display an error to the user; may be called after any of the prompts */ - kim_error (*display_error) (void *in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description); + kim_error (*handle_error) (void *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); - /* Free strings returned by the UI */ - void (*free_string) (void *in_context, - char *io_string); + /* Free strings returned by the UI. Will be called once for each string + * returned from a plugin callback. If you have returned a string twice + * just make sure your free function checks for NULL and sets the pointer + * to NULL when done freeing memory. */ + void (*free_string) (void *in_context, + char **io_string); /* Called after the last prompt (even on error) to allow the UI to * free allocated resources associated with its context. */ diff --git a/src/kim/lib/kim-lite.exports b/src/kim/lib/kim-lite.exports index ebad7bf94..1b8466a56 100644 --- a/src/kim/lib/kim-lite.exports +++ b/src/kim/lib/kim-lite.exports @@ -16,20 +16,10 @@ kim_identity_get_number_of_components kim_identity_get_component_at_index kim_identity_get_krb5_principal kim_identity_change_password -kim_identity_change_password_to_password kim_identity_free -kim_prompt_callback_default -kim_prompt_callback_gui -kim_prompt_callback_cli -kim_prompt_callback_none - kim_options_create kim_options_copy -kim_options_set_prompt_callback -kim_options_get_prompt_callback -kim_options_set_data -kim_options_get_data kim_options_set_start_time kim_options_get_start_time kim_options_set_lifetime @@ -91,6 +81,7 @@ kim_credential_iterator_free kim_credential_create_new kim_credential_create_from_krb5_creds +kim_credential_create_for_change_password kim_credential_copy kim_credential_get_krb5_creds kim_credential_get_client_identity @@ -103,6 +94,7 @@ kim_credential_get_renewal_expiration_time kim_credential_store kim_credential_renew kim_credential_validate +kim_credential_change_password kim_credential_free kim_ccache_iterator_create diff --git a/src/kim/lib/kim.exports b/src/kim/lib/kim.exports index a408815b6..d2f2e27e7 100644 --- a/src/kim/lib/kim.exports +++ b/src/kim/lib/kim.exports @@ -16,14 +16,8 @@ kim_identity_get_number_of_components kim_identity_get_component_at_index kim_identity_get_krb5_principal kim_identity_change_password -kim_identity_change_password_to_password kim_identity_free -kim_prompt_callback_default -kim_prompt_callback_gui -kim_prompt_callback_cli -kim_prompt_callback_none - kim_options_create kim_options_copy kim_options_set_start_time @@ -88,6 +82,7 @@ kim_credential_iterator_free kim_credential_create_new kim_credential_create_from_keytab kim_credential_create_from_krb5_creds +kim_credential_create_for_change_password kim_credential_copy kim_credential_get_krb5_creds kim_credential_get_client_identity @@ -101,6 +96,7 @@ kim_credential_store kim_credential_verify kim_credential_renew kim_credential_validate +kim_credential_change_password kim_credential_free kim_ccache_iterator_create diff --git a/src/kim/lib/kim_credential.c b/src/kim/lib/kim_credential.c index 9952a9c72..f81b50f12 100644 --- a/src/kim/lib/kim_credential.c +++ b/src/kim/lib/kim_credential.c @@ -179,12 +179,19 @@ static inline kim_error kim_credential_allocate (kim_credential *out_credential) /* ------------------------------------------------------------------------ */ kim_error kim_credential_create_new (kim_credential *out_credential, - kim_identity in_client_identity, + kim_identity in_identity, kim_options in_options) { kim_error err = KIM_NO_ERROR; kim_credential credential = NULL; - + kim_options options = NULL; + kim_ui_context context; + kim_string service = NULL; + krb5_principal principal = NULL; + krb5_get_init_creds_opt *init_cred_options = NULL; + kim_boolean ui_inited = 0; + kim_boolean done = 0; + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { @@ -196,7 +203,82 @@ kim_error kim_credential_create_new (kim_credential *out_credential, } if (!err) { -#warning Get tickets here + if (in_options) { + options = in_options; + } else { + err = kim_options_create (&options); + } + } + + if (!err) { + err = kim_options_get_init_cred_options (options, + credential->context, + &init_cred_options); + } + + if (!err) { + kim_options_get_service_name (options, &service); + } + + if (!err) { + err = kim_identity_get_krb5_principal (in_identity, + credential->context, + &principal); + } + + if (!err) { + err = kim_ui_init (&context); + if (!err) { + context.identity = in_identity; /* used by kim_ui_prompter */ + ui_inited = 1; + } + } + + while (!err && !done) { + krb5_creds creds; + kim_boolean free_creds = 0; + + err = krb5_error (credential->context, + krb5_get_init_creds_password (credential->context, + &creds, + principal, + NULL, + kim_ui_prompter, + &context, 0, + (char *) service, + init_cred_options)); + + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + + if (!err || err == KIM_USER_CANCELED_ERR) { + /* new creds obtained or the user gave up */ + done = 1; + + } else { + /* new creds failed, report error to user */ + err = kim_ui_handle_kim_error (&context, in_identity, + kim_ui_error_type_authentication, + err); + } + + if (free_creds) { krb5_free_cred_contents (credential->context, &creds); } + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = check_error (fini_err); } + } + + /* free before credential is passed back to caller */ + if (credential && init_cred_options) { + kim_options_free_init_cred_options (credential->context, &init_cred_options); } if (!err) { @@ -204,6 +286,9 @@ kim_error kim_credential_create_new (kim_credential *out_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); return check_error (err); @@ -362,7 +447,9 @@ kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, } if (!err) { - err = krb5_error (NULL, krb5_init_context (&credential->context)); + err = krb5_error (in_krb5_context, + krb5_copy_context (in_krb5_context, + &credential->context)); } if (!err) { @@ -382,6 +469,117 @@ 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_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_string realm = NULL; + kim_string service = NULL; + kim_ui_context context; + krb5_principal principal = NULL; + kim_string service_format = "kadmin/changepw@%s"; + kim_boolean ui_inited = 0; + kim_boolean done = 0; + + 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) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&credential->context)); + } + + if (!err) { + err = kim_identity_get_krb5_principal (in_identity, + credential->context, + &principal); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + err = kim_string_create_from_format (&service, service_format, realm); + } + + if (!err) { + err = kim_ui_init (&context); + if (!err) { + context.identity = in_identity; /* used by kim_ui_prompter */ + ui_inited = 1; + } + } + + while (!err && !done) { + krb5_creds creds; + kim_boolean free_creds = 0; + krb5_get_init_creds_opt opts; + + krb5_get_init_creds_opt_init (&opts); + krb5_get_init_creds_opt_set_tkt_life (&opts, 5*60); + krb5_get_init_creds_opt_set_renew_life (&opts, 0); + krb5_get_init_creds_opt_set_forwardable (&opts, 0); + krb5_get_init_creds_opt_set_proxiable (&opts, 0); + + err = krb5_error (credential->context, + krb5_get_init_creds_password (credential->context, + &creds, + principal, + (char *) in_old_password, + kim_ui_prompter, + &context, 0, (char *) service, + &opts)); + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + + if (!err || err == KIM_USER_CANCELED_ERR) { + /* new creds obtained or the user gave up */ + done = 1; + + } else { + /* new creds failed, report error to user */ + err = kim_ui_handle_kim_error (&context, in_identity, + kim_ui_error_type_change_password, + err); + } + + if (free_creds) { krb5_free_cred_contents (credential->context, &creds); } + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = check_error (fini_err); } + } + + if (!err) { + *out_credential = credential; + credential = NULL; + } + + if (principal ) { krb5_free_principal (credential->context, principal); } + + kim_string_free (&realm); + kim_string_free (&service); + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_credential_copy (kim_credential *out_credential, kim_credential in_credential) { @@ -396,7 +594,9 @@ kim_error kim_credential_copy (kim_credential *out_credential, } if (!err) { - err = krb5_error (NULL, krb5_init_context (&credential->context)); + err = krb5_error (in_credential->context, + krb5_copy_context (in_credential->context, + &credential->context)); } if (!err) { @@ -690,8 +890,6 @@ kim_error kim_credential_store (kim_credential in_credential, k5ccache, in_credential->creds)); } -#warning Call plugins here - if (!err && out_ccache) { err = kim_ccache_create_from_krb5_ccache (out_ccache, context, k5ccache); } @@ -966,6 +1164,130 @@ kim_error kim_credential_validate (kim_credential *io_credential, /* ------------------------------------------------------------------------ */ +kim_error kim_credential_change_password (kim_credential in_credential, + kim_identity in_identity, + kim_string in_new_password, + kim_error *out_rejected_err, + kim_string *out_rejected_message, + kim_string *out_rejected_description) +{ + kim_error err = KIM_NO_ERROR; + krb5_principal principal = NULL; + int rejected_code = 0; + krb5_data message_data; + krb5_data description_data; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_rejected_err) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* out_rejected_message and out_rejected_description may be NULL */ + + if (!err) { + err = kim_identity_get_krb5_principal (in_identity, + in_credential->context, + &principal); + } + + if (!err) { + err = krb5_error (in_credential->context, + krb5_principal_compare (in_credential->context, + in_credential->creds->client, + principal)); + } + + if (!err) { + if (krb5_principal_compare (in_credential->context, + in_credential->creds->client, + principal)) { + /* Same principal, change the password normally */ + err = krb5_error (in_credential->context, + krb5_change_password (in_credential->context, + in_credential->creds, + (char *) in_new_password, + &rejected_code, + &message_data, + &description_data)); + } else { + /* Different principal, use set change password protocol */ + err = krb5_error (in_credential->context, + krb5_set_password (in_credential->context, + in_credential->creds, + (char *) in_new_password, + principal, + &rejected_code, + &message_data, + &description_data)); + } + + } + + if (!err && rejected_code) { + kim_string rejected_message = NULL; + kim_string rejected_description = NULL; + + if (!err) { + if (message_data.data && message_data.length > 0) { + err = kim_string_create_from_buffer (&rejected_message, + message_data.data, + message_data.length); + } else { + err = kim_os_string_create_localized (&rejected_message, + "KLStringChangePasswordFailed"); + } + } + + if (!err) { + if (description_data.data && description_data.length > 0) { + err = kim_string_create_from_buffer (&rejected_description, + description_data.data, + description_data.length); + } else { + err = kim_os_string_create_localized (&rejected_description, + "KLStringPasswordRejected"); + } + } + + if (!err) { + char *c; + + // replace all \n and \r characters with spaces + for (c = (char *) rejected_message; *c != '\0'; c++) { + if ((*c == '\n') || (*c == '\r')) { *c = ' '; } + } + + for (c = (char *) rejected_description; *c != '\0'; c++) { + if ((*c == '\n') || (*c == '\r')) { *c = ' '; } + } + } + + if (!err) { + if (out_rejected_message) { + *out_rejected_message = rejected_message; + rejected_message = NULL; + } + + if (out_rejected_description) { + *out_rejected_description = rejected_description; + rejected_description = NULL; + } + } + + kim_string_free (&rejected_message); + kim_string_free (&rejected_description); + + krb5_free_data_contents (in_credential->context, &message_data); + krb5_free_data_contents (in_credential->context, &description_data); + } + + if (!err) { + *out_rejected_err = rejected_code; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + void kim_credential_free (kim_credential *io_credential) { if (io_credential && *io_credential) { diff --git a/src/kim/lib/kim_identity.c b/src/kim/lib/kim_identity.c index e427a2a1b..7a5b68a9f 100644 --- a/src/kim/lib/kim_identity.c +++ b/src/kim/lib/kim_identity.c @@ -91,10 +91,6 @@ kim_error kim_identity_create_from_string (kim_identity *out_identity, } } - if (!err) { -#warning Run translator here - } - if (!err) { *out_identity = identity; identity = NULL; @@ -174,10 +170,6 @@ kim_error kim_identity_create_from_components (kim_identity *out_identity, &identity->principal)); } - if (!err) { -#warning Run translator here - } - if (!err) { *out_identity = identity; identity = NULL; @@ -225,10 +217,6 @@ kim_error kim_identity_create_from_krb5_principal (kim_identity *out_identity, &identity->principal)); } - if (!err) { -#warning Run translator here - } - if (!err) { *out_identity = identity; identity = NULL; @@ -253,7 +241,9 @@ kim_error kim_identity_copy (kim_identity *out_identity, err = kim_identity_allocate (&identity); if (!err) { - err = krb5_error (NULL, krb5_init_context (&identity->context)); + err = krb5_error (in_identity->context, + krb5_copy_context (in_identity->context, + &identity->context)); } if (!err) { @@ -546,33 +536,97 @@ kim_error kim_identity_is_tgt_service (kim_identity in_identity, /* ------------------------------------------------------------------------ */ -kim_error kim_identity_change_password (kim_identity in_identity, - kim_options in_options) +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; + kim_boolean done = 0; if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { -#warning Implement change password GUI support + err = kim_ui_init (&context); + if (!err) { ui_inited = 1; } } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_identity_change_password_to_password (kim_identity in_identity, - kim_options in_options, - kim_string in_new_password) -{ - kim_error err = KIM_NO_ERROR; - if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_new_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + while (!err && !done) { + char *old_password = NULL; + char *new_password = NULL; + char *verify_password = NULL; + kim_error rejected_err = KIM_NO_ERROR; + kim_string rejected_message = NULL; + kim_string rejected_description = NULL; + + err = kim_ui_change_password (&context, + in_identity, + 0 /* old password not expired */, + &old_password, + &new_password, + &verify_password); + + if (!err) { + kim_comparison 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); + } + } + + if (!err) { + kim_credential credential = NULL; + + if (context.type == kim_ui_type_cli && context.tcontext) { + /* command line has already gotten the credentials for us */ + credential = (kim_credential) context.tcontext; + } else { + err = kim_credential_create_for_change_password (&credential, + in_identity, + old_password); + } + + if (!err) { + err = kim_credential_change_password (credential, + in_identity, + new_password, + &rejected_err, + &rejected_message, + &rejected_description); + + } + + kim_credential_free (&credential); + } + + if (!err || err == KIM_USER_CANCELED_ERR) { + /* password change succeeded or the user gave up */ + done = 1; + + } else if (!err && rejected_err) { + /* Password rejected, report it to the user */ + err = kim_ui_handle_error (&context, in_identity, + rejected_err, + rejected_message, + rejected_description); + + } else { + /* Password change failed, report error to user */ + err = kim_ui_handle_kim_error (&context, in_identity, + kim_ui_error_type_change_password, + err); + } + + 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); + } - if (!err) { -#warning Implement change password support + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = check_error (fini_err); } } return check_error (err); diff --git a/src/kim/lib/kim_options.c b/src/kim/lib/kim_options.c index dbb024c2d..102fa9644 100644 --- a/src/kim/lib/kim_options.c +++ b/src/kim/lib/kim_options.c @@ -29,8 +29,6 @@ /* ------------------------------------------------------------------------ */ struct kim_options_opaque { - kim_prompt_callback prompt_callback; - const void *prompt_callback_data; kim_time start_time; kim_lifetime lifetime; kim_boolean renewable; @@ -42,7 +40,6 @@ struct kim_options_opaque { }; struct kim_options_opaque kim_options_initializer = { -NULL, NULL, 0, kim_default_lifetime, kim_default_renewable, @@ -120,11 +117,6 @@ kim_error kim_options_copy (kim_options *out_options, if (!err && in_options != KIM_OPTIONS_DEFAULT) { err = kim_options_allocate (&options); - if (!err) { - options->prompt_callback = in_options->prompt_callback; - options->prompt_callback_data = in_options->prompt_callback_data; - } - if (!err) { options->start_time = in_options->start_time; options->lifetime = in_options->lifetime; @@ -153,73 +145,6 @@ kim_error kim_options_copy (kim_options *out_options, /* ------------------------------------------------------------------------ */ -kim_error kim_options_set_prompt_callback (kim_options io_options, - kim_prompt_callback in_prompt_callback) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - io_options->prompt_callback = in_prompt_callback; - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_options_get_prompt_callback (kim_options in_options, - kim_prompt_callback *out_prompt_callback) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_prompt_callback) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - *out_prompt_callback = in_options->prompt_callback; - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_options_set_data (kim_options io_options, - const void *in_data) - -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - io_options->prompt_callback_data = in_data; - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_options_get_data (kim_options in_options, - const void **out_data) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !in_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_data ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - *out_data = in_options->prompt_callback_data; - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - kim_error kim_options_set_start_time (kim_options io_options, kim_time in_start_time) { @@ -507,22 +432,29 @@ kim_error kim_options_get_init_cred_options (kim_options in_option if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_init_cred_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_options->addressless) { - err = krb5_error (in_context, - krb5_os_localaddr (in_context, &addresses)); - } - if (!err) { krb5_get_init_creds_opt_alloc (in_context, &init_cred_options); - krb5_get_init_creds_opt_set_tkt_life (init_cred_options, in_options->lifetime); - krb5_get_init_creds_opt_set_renew_life (init_cred_options, in_options->renewable ? in_options->renewal_lifetime : 0); - krb5_get_init_creds_opt_set_forwardable (init_cred_options, in_options->forwardable); - krb5_get_init_creds_opt_set_proxiable (init_cred_options, in_options->proxiable); - krb5_get_init_creds_opt_set_address_list (init_cred_options, addresses); + } + + if (!err && in_options) { + if (!in_options->addressless) { + err = krb5_error (in_context, + krb5_os_localaddr (in_context, &addresses)); + } - *out_init_cred_options = init_cred_options; - init_cred_options = NULL; - addresses = NULL; + if (!err) { + krb5_get_init_creds_opt_set_tkt_life (init_cred_options, in_options->lifetime); + krb5_get_init_creds_opt_set_renew_life (init_cred_options, in_options->renewable ? in_options->renewal_lifetime : 0); + krb5_get_init_creds_opt_set_forwardable (init_cred_options, in_options->forwardable); + krb5_get_init_creds_opt_set_proxiable (init_cred_options, in_options->proxiable); + krb5_get_init_creds_opt_set_address_list (init_cred_options, addresses); + addresses = NULL; + } + } + + if (!err) { + *out_init_cred_options = init_cred_options; + init_cred_options = NULL; } if (init_cred_options) { krb5_get_init_creds_opt_free (in_context, init_cred_options); } @@ -543,6 +475,7 @@ kim_error kim_options_free_init_cred_options (krb5_context in_conte if (!err && io_init_cred_options && *io_init_cred_options) { if ((*io_init_cred_options)->address_list) { krb5_free_addresses (in_context, (*io_init_cred_options)->address_list); + (*io_init_cred_options)->address_list = NULL; } krb5_get_init_creds_opt_free (in_context, *io_init_cred_options); *io_init_cred_options = NULL; @@ -561,70 +494,3 @@ void kim_options_free (kim_options *io_options) *io_options = NULL; } } - -#pragma mark - - -/* ------------------------------------------------------------------------ */ - -kim_error kim_prompt_callback_default (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_prompt_callback_gui (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_prompt_callback_cli (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - } - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_prompt_callback_none (kim_prompt_type in_type, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) -{ - return KIM_USER_CANCELED_ERR; -} diff --git a/src/kim/lib/kim_selection_hints.c b/src/kim/lib/kim_selection_hints.c index 78a4c03e8..1aa8555d8 100644 --- a/src/kim/lib/kim_selection_hints.c +++ b/src/kim/lib/kim_selection_hints.c @@ -478,7 +478,19 @@ kim_error kim_selection_hints_get_identity (kim_selection_hints in_selection_hi } if (!err && !identity && in_selection_hints->allow_user_interaction) { -#warning GUI to let user pick identity here + kim_ui_context context; + + err = kim_ui_init (&context); + + if (!err) { + err = kim_ui_select_identity (&context, + in_selection_hints, + &identity); + } + + if (!err) { + err = kim_ui_fini (&context); + } } if (!err) { diff --git a/src/kim/lib/kim_string.c b/src/kim/lib/kim_string.c index 94bdb7a89..6968f19d9 100644 --- a/src/kim/lib/kim_string.c +++ b/src/kim/lib/kim_string.c @@ -147,6 +147,7 @@ kim_error kim_string_compare (kim_string in_string, { return kim_os_string_compare (in_string, in_compare_to_string, + 0, /* case sensitive */ out_comparison); } diff --git a/src/kim/lib/kim_string_private.h b/src/kim/lib/kim_string_private.h index 8998ac7f3..4b1cc1839 100644 --- a/src/kim/lib/kim_string_private.h +++ b/src/kim/lib/kim_string_private.h @@ -55,6 +55,10 @@ kim_error kim_string_append (kim_string *io_string, /* OS-specific because it should use UTF8-safe sorting where possible */ kim_error kim_os_string_compare (kim_string in_string, kim_string in_compare_to_string, + kim_boolean in_case_insensitive, kim_comparison *out_comparison); +kim_error kim_os_string_create_localized (kim_string *out_string, + kim_string in_string); + #endif /* KIM_STRING_PRIVATE_H */ diff --git a/src/kim/lib/kim_ui.c b/src/kim/lib/kim_ui.c index 1ef364771..36920144e 100644 --- a/src/kim/lib/kim_ui.c +++ b/src/kim/lib/kim_ui.c @@ -27,6 +27,78 @@ #include "kim_private.h" +/* ------------------------------------------------------------------------ */ + +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; + } + 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 - + /* ------------------------------------------------------------------------ */ kim_error kim_ui_init (kim_ui_context *io_context) @@ -36,13 +108,15 @@ kim_error kim_ui_init (kim_ui_context *io_context) if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } 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; err = kim_ui_plugin_init ((kim_ui_plugin_context *) &io_context->tcontext); - +#ifndef LEAN_CLIENT if (err) { io_context->type = kim_ui_type_gui_builtin; @@ -59,6 +133,7 @@ kim_error kim_ui_init (kim_ui_context *io_context) err = check_error (KIM_NO_UI_ERR); } +#endif /* LEAN_CLIENT */ } return check_error (err); @@ -66,6 +141,40 @@ kim_error kim_ui_init (kim_ui_context *io_context) /* ------------------------------------------------------------------------ */ +kim_error kim_ui_enter_identity (kim_ui_context *in_context, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_enter_identity ((kim_ui_plugin_context) in_context->tcontext, + out_identity); + +#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); + + } else if (in_context->type == kim_ui_type_cli) { + err = kim_ui_cli_enter_identity ((kim_ui_cli_context) in_context->tcontext, + out_identity); + +#endif /* LEAN_CLIENT */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_ui_select_identity (kim_ui_context *in_context, kim_selection_hints in_hints, kim_identity *out_identity) @@ -82,6 +191,7 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, in_hints, out_identity); +#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, @@ -92,6 +202,8 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, in_hints, out_identity); +#endif /* LEAN_CLIENT */ + } else { err = check_error (KIM_NO_UI_ERR); } @@ -105,6 +217,7 @@ kim_error kim_ui_select_identity (kim_ui_context *in_context, 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, @@ -122,15 +235,18 @@ kim_error kim_ui_auth_prompt (kim_ui_context *in_context, 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, @@ -140,10 +256,12 @@ kim_error kim_ui_auth_prompt (kim_ui_context *in_context, 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); +#endif /* LEAN_CLIENT */ } else { err = check_error (KIM_NO_UI_ERR); @@ -179,6 +297,7 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, out_new_password, out_verify_password); +#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, @@ -195,6 +314,8 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, out_new_password, out_verify_password); +#endif /* LEAN_CLIENT */ + } else { err = check_error (KIM_NO_UI_ERR); } @@ -203,13 +324,65 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, return check_error (err); } +/* ------------------------------------------------------------------------ */ +/* Helper function */ + +kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, + kim_identity in_identity, + enum kim_ui_error_type in_type, + kim_error in_error) +{ + kim_error err = KIM_NO_ERROR; + kim_string message = NULL; + kim_string description = NULL; + + if (!err) { + /* Do this first so last error doesn't get overwritten */ + err = kim_string_get_last_error_message (&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"; + break; + + case kim_ui_error_type_change_password: + key = "KLStringChangePasswordFailed"; + break; + + case kim_ui_error_type_selection: + case kim_ui_error_type_generic: + default: + key = "KLStringKerberosOperationFailed"; + break; + } + + err = kim_os_string_create_localized (&message, key); + } + + if (!err) { + err = kim_ui_handle_error (in_context, in_identity, + in_error, message, description); + } + + kim_string_free (&description); + kim_string_free (&message); + + return check_error (err); +} + /* ------------------------------------------------------------------------ */ -kim_error kim_ui_display_error (kim_ui_context *in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description) +kim_error kim_ui_handle_error (kim_ui_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; @@ -219,25 +392,27 @@ kim_error kim_ui_display_error (kim_ui_context *in_context, if (!err) { if (in_context->type == kim_ui_type_gui_plugin) { - err = kim_ui_plugin_display_error ((kim_ui_plugin_context) in_context->tcontext, + err = kim_ui_plugin_handle_error ((kim_ui_plugin_context) in_context->tcontext, 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_display_error ((kim_ui_gui_context) in_context->tcontext, + err = kim_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_display_error ((kim_ui_cli_context) in_context->tcontext, + err = kim_ui_cli_handle_error ((kim_ui_cli_context) in_context->tcontext, in_identity, in_error, in_error_message, in_error_description); +#endif /* LEAN_CLIENT */ } else { err = check_error (KIM_NO_UI_ERR); @@ -249,19 +424,15 @@ kim_error kim_ui_display_error (kim_ui_context *in_context, /* ------------------------------------------------------------------------ */ -void kim_ui_free_string (kim_ui_context *in_context, - char *io_string) +void kim_ui_free_string (kim_ui_context *in_context, + char **io_string) { - kim_error err = KIM_NO_ERROR; - - if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !io_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { + if (in_context && io_string && *io_string) { if (in_context->type == kim_ui_type_gui_plugin) { kim_ui_plugin_free_string ((kim_ui_plugin_context) in_context->tcontext, io_string); +#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); @@ -269,9 +440,8 @@ void kim_ui_free_string (kim_ui_context *in_context, } else if (in_context->type == kim_ui_type_cli) { kim_ui_cli_free_string ((kim_ui_cli_context) in_context->tcontext, io_string); +#endif /* LEAN_CLIENT */ - } else { - err = check_error (KIM_NO_UI_ERR); } } } @@ -285,14 +455,18 @@ 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); } else if (io_context->type == kim_ui_type_cli) { err = kim_ui_cli_fini ((kim_ui_cli_context *) &io_context->tcontext); +#endif /* LEAN_CLIENT */ } else { err = check_error (KIM_NO_UI_ERR); diff --git a/src/kim/lib/kim_ui_cli.c b/src/kim/lib/kim_ui_cli.c index d4ba76f58..898b58086 100644 --- a/src/kim/lib/kim_ui_cli.c +++ b/src/kim/lib/kim_ui_cli.c @@ -24,19 +24,112 @@ * or implied warranty. */ +#ifndef LEAN_CLIENT + #include "kim_private.h" +// --------------------------------------------------------------------------- +static kim_error kim_ui_cli_read_string (kim_string *out_string, + kim_boolean in_hide_reply, + const char *in_format, ...) +{ + kim_error err = KIM_NO_ERROR; + krb5_context k5context = NULL; + krb5_prompt prompts[1]; + char prompt_string [BUFSIZ]; + krb5_data reply_data; + char reply_string [BUFSIZ]; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_init_context (&k5context); + } + + if (!err) { + unsigned int count; + va_list args; + + va_start (args, in_format); + count = vsnprintf (prompt_string, sizeof (prompt_string), + in_format, args); + va_end (args); + + if (count > sizeof (prompt_string)) { + kim_debug_printf ("%s(): WARNING! Prompt should be %d characters\n", + __FUNCTION__, count); + prompt_string [sizeof (prompt_string) - 1] = '\0'; + } + } + + if (!err) { + /* Build the prompt structures */ + prompts[0].prompt = prompt_string; + prompts[0].hidden = in_hide_reply; + prompts[0].reply = &reply_data; + prompts[0].reply->data = reply_string; + prompts[0].reply->length = sizeof (reply_string); + + err = krb5_prompter_posix (k5context, NULL, NULL, NULL, 1, prompts); + if (err == KRB5_LIBOS_PWDINTR) { err = check_error (KIM_USER_CANCELED_ERR); } + } + + if (!err) { + err = kim_string_create_from_buffer (out_string, + prompts[0].reply->data, + prompts[0].reply->length); + } + + if (k5context) { krb5_free_context (k5context); } + + return check_error (err); +} /* ------------------------------------------------------------------------ */ kim_error kim_ui_cli_init (kim_ui_cli_context *out_context) { + *out_context = NULL; + return KIM_NO_ERROR; } /* ------------------------------------------------------------------------ */ +kim_error kim_ui_cli_enter_identity (kim_ui_cli_context in_context, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_string enter_identity_string = NULL; + kim_string identity_string = NULL; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_create_localized (&enter_identity_string, + "KLStringEnterPrincipal"); + } + + if (!err) { + err = kim_ui_cli_read_string (&identity_string, + 0, enter_identity_string); + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity_string); + } + + kim_string_free (&identity_string); + kim_string_free (&enter_identity_string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_ui_cli_select_identity (kim_ui_cli_context in_context, kim_selection_hints in_hints, kim_identity *out_identity) @@ -48,6 +141,7 @@ kim_error kim_ui_cli_select_identity (kim_ui_cli_context in_context, if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { + err = kim_ui_cli_enter_identity (in_context, out_identity); } return check_error (err); @@ -58,6 +152,7 @@ kim_error kim_ui_cli_select_identity (kim_ui_cli_context in_context, kim_error kim_ui_cli_auth_prompt (kim_ui_cli_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, @@ -71,6 +166,55 @@ kim_error kim_ui_cli_auth_prompt (kim_ui_cli_context in_context, /* in_title, in_message or in_description may be NULL */ if (!err) { + if (in_type == kim_prompt_type_password) { + kim_string enter_password_format = NULL; + kim_string identity_string = NULL; + + err = kim_os_string_create_localized (&enter_password_format, + "KLStringEnterPassword"); + + if (!err) { + err = kim_identity_get_display_string (in_identity, + &identity_string); + } + + if (!err) { + err = kim_ui_cli_read_string ((kim_string *) out_reply, + 1, enter_password_format, + identity_string); + } + + kim_string_free (&identity_string); + kim_string_free (&enter_password_format); + + } else { + krb5_context k5context = NULL; + krb5_prompt prompts[1]; + krb5_data reply_data; + char reply_string [BUFSIZ]; + + prompts[0].prompt = (char *) in_description; + prompts[0].hidden = in_hide_reply; + prompts[0].reply = &reply_data; + prompts[0].reply->data = reply_string; + prompts[0].reply->length = sizeof (reply_string); + + err = krb5_init_context (&k5context); + + if (!err) { + err = krb5_prompter_posix (k5context, in_context, in_title, + in_message, 1, prompts); + if (err == KRB5_LIBOS_PWDINTR) { err = check_error (KIM_USER_CANCELED_ERR); } + } + + if (!err) { + err = kim_string_create_from_buffer ((kim_string *) out_reply, + prompts[0].reply->data, + prompts[0].reply->length); + } + + if (k5context) { krb5_free_context (k5context); } + } } return check_error (err); @@ -78,6 +222,88 @@ kim_error kim_ui_cli_auth_prompt (kim_ui_cli_context in_context, /* ------------------------------------------------------------------------ */ +static kim_error kim_ui_cli_ask_change_password (kim_string in_identity_string) +{ + kim_error err = KIM_NO_ERROR; + kim_string ask_change_password = NULL; + kim_string answer_options = NULL; + kim_string yes = NULL; + kim_string no = NULL; + kim_string unknown_response = NULL; + kim_boolean done = 0; + kim_comparison no_comparison, yes_comparison; + + if (!err) { + err = kim_os_string_create_localized (&ask_change_password, + "KLStringPasswordExpired"); + } + + if (!err) { + err = kim_os_string_create_localized (&answer_options, + "KLStringYesOrNoAnswerOptions"); + } + + if (!err) { + err = kim_os_string_create_localized (&yes, + "KLStringYes"); + } + + if (!err) { + err = kim_os_string_create_localized (&no, + "KLStringNo"); + } + + if (!err) { + err = kim_os_string_create_localized (&unknown_response, + "KLStringUnknownResponse"); + } + + while (!err && !done) { + kim_string answer = NULL; + + err = kim_ui_cli_read_string (&answer, + 0, "%s %s", + ask_change_password, answer_options); + + if (!err) { + err = kim_os_string_compare (answer, no, + 1 /* case insensitive */, + &no_comparison); + } + + if (!err && kim_comparison_is_equal_to (no_comparison)) { + err = check_error (KIM_USER_CANCELED_ERR); + } + + if (!err) { + err = kim_os_string_compare (answer, yes, + 1 /* case insensitive */, + &yes_comparison); + } + + if (!err) { + if (kim_comparison_is_equal_to (yes_comparison)) { + done = 1; + } else { + fprintf (stdout, unknown_response, answer); + fprintf (stdout, "\n"); + } + } + + kim_string_free (&answer); + } + + kim_string_free (&ask_change_password); + kim_string_free (&answer_options); + kim_string_free (&yes); + kim_string_free (&no); + kim_string_free (&unknown_response); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_ui_cli_change_password (kim_ui_cli_context in_context, kim_identity in_identity, kim_boolean in_old_password_expired, @@ -86,6 +312,13 @@ kim_error kim_ui_cli_change_password (kim_ui_cli_context in_context, char **out_verify_password) { kim_error err = KIM_NO_ERROR; + kim_string enter_old_password_format = NULL; + kim_string enter_new_password_format = NULL; + kim_string enter_verify_password_format = NULL; + kim_string identity_string = NULL; + kim_string old_password = NULL; + kim_string new_password = NULL; + kim_string verify_password = NULL; if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } @@ -94,18 +327,79 @@ kim_error kim_ui_cli_change_password (kim_ui_cli_context in_context, if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { + err = kim_identity_get_display_string (in_identity, &identity_string); + } + + if (!err && in_old_password_expired) { + err = kim_ui_cli_ask_change_password (identity_string); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_old_password_format, + "KLStringEnterOldPassword"); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_new_password_format, + "KLStringEnterNewPassword"); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_verify_password_format, + "KLStringEnterVerifyPassword"); + } + + if (!err) { + err = kim_ui_cli_read_string (&old_password, + 1, enter_old_password_format, + identity_string); + } + + if (!err) { + err = kim_credential_create_for_change_password (&in_context, + in_identity, + old_password); + } + + if (!err) { + err = kim_ui_cli_read_string (&new_password, + 1, enter_new_password_format, + identity_string); + } + + if (!err) { + err = kim_ui_cli_read_string (&verify_password, + 1, enter_new_password_format, + identity_string); + } + + if (!err) { + *out_old_password = (char *) old_password; + old_password = NULL; + *out_new_password = (char *) new_password; + new_password = NULL; + *out_verify_password = (char *) verify_password; + verify_password = NULL; } + kim_string_free (&old_password); + kim_string_free (&new_password); + kim_string_free (&verify_password); + kim_string_free (&identity_string); + kim_string_free (&enter_old_password_format); + kim_string_free (&enter_new_password_format); + kim_string_free (&enter_verify_password_format); + return check_error (err); } /* ------------------------------------------------------------------------ */ -kim_error kim_ui_cli_display_error (kim_ui_cli_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description) +kim_error kim_ui_cli_handle_error (kim_ui_cli_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; @@ -114,6 +408,7 @@ kim_error kim_ui_cli_display_error (kim_ui_cli_context in_context, if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { + fprintf (stdout, "%s: %s\n", in_error_message, in_error_description); } return check_error (err); @@ -121,22 +416,21 @@ kim_error kim_ui_cli_display_error (kim_ui_cli_context in_context, /* ------------------------------------------------------------------------ */ -void kim_ui_cli_free_string (kim_ui_cli_context in_context, - char *io_string) +void kim_ui_cli_free_string (kim_ui_cli_context in_context, + char **io_string) { - kim_error err = KIM_NO_ERROR; - - if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !io_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - kim_string_free ((kim_string *) io_string); - } + kim_string_free ((kim_string *) io_string); } /* ------------------------------------------------------------------------ */ kim_error kim_ui_cli_fini (kim_ui_cli_context *io_context) { + if (io_context && *io_context) { + kim_credential_free (io_context); + } + return KIM_NO_ERROR; } + +#endif /* LEAN_CLIENT */ diff --git a/src/kim/lib/kim_ui_cli_private.h b/src/kim/lib/kim_ui_cli_private.h index cc5ff7f0c..89011aa3a 100644 --- a/src/kim/lib/kim_ui_cli_private.h +++ b/src/kim/lib/kim_ui_cli_private.h @@ -27,13 +27,18 @@ #ifndef KIM_UI_CLI_PRIVATE_H #define KIM_UI_CLI_PRIVATE_H +#ifndef LEAN_CLIENT + #include -typedef void *kim_ui_cli_context; +typedef kim_credential kim_ui_cli_context; kim_error kim_ui_cli_init (kim_ui_cli_context *out_context); +kim_error kim_ui_cli_enter_identity (kim_ui_cli_context in_context, + kim_identity *out_identity); + kim_error kim_ui_cli_select_identity (kim_ui_cli_context in_context, kim_selection_hints in_hints, kim_identity *out_identity); @@ -41,6 +46,7 @@ kim_error kim_ui_cli_select_identity (kim_ui_cli_context in_context, kim_error kim_ui_cli_auth_prompt (kim_ui_cli_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, @@ -53,15 +59,17 @@ kim_error kim_ui_cli_change_password (kim_ui_cli_context in_context, char **out_new_password, char **out_verify_password); -kim_error kim_ui_cli_display_error (kim_ui_cli_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description); +kim_error kim_ui_cli_handle_error (kim_ui_cli_context in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); -void kim_ui_cli_free_string (kim_ui_cli_context in_context, - char *io_string); +void kim_ui_cli_free_string (kim_ui_cli_context in_context, + char **io_string); kim_error kim_ui_cli_fini (kim_ui_cli_context *io_context); +#endif /* LEAN_CLIENT */ + #endif /* KIM_UI_CLI_PRIVATE_H */ diff --git a/src/kim/lib/kim_ui_gui.c b/src/kim/lib/kim_ui_gui.c index 56d0401fa..9eb41e457 100644 --- a/src/kim/lib/kim_ui_gui.c +++ b/src/kim/lib/kim_ui_gui.c @@ -24,6 +24,8 @@ * or implied warranty. */ +#ifndef LEAN_CLIENT + #include "kim_private.h" @@ -95,6 +97,22 @@ kim_error kim_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 err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_ui_gui_select_identity (kim_ui_gui_context in_context, kim_selection_hints in_hints, kim_identity *out_identity) @@ -116,6 +134,7 @@ 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, @@ -159,11 +178,11 @@ kim_error kim_ui_gui_change_password (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_gui_display_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_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; @@ -179,17 +198,10 @@ kim_error kim_ui_gui_display_error (kim_ui_gui_context in_context, /* ------------------------------------------------------------------------ */ -void kim_ui_gui_free_string (kim_ui_gui_context in_context, - char *io_string) +void kim_ui_gui_free_string (kim_ui_gui_context in_context, + char **io_string) { - kim_error err = KIM_NO_ERROR; - - if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !io_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { - kim_string_free ((kim_string *) io_string); - } + kim_string_free ((kim_string *) io_string); } /* ------------------------------------------------------------------------ */ @@ -210,3 +222,5 @@ kim_error kim_ui_gui_fini (kim_ui_gui_context *io_context) return check_error (err); } + +#endif /* LEAN_CLIENT */ diff --git a/src/kim/lib/kim_ui_gui_private.h b/src/kim/lib/kim_ui_gui_private.h index 9ddffb19a..b6d2ebd52 100644 --- a/src/kim/lib/kim_ui_gui_private.h +++ b/src/kim/lib/kim_ui_gui_private.h @@ -27,6 +27,8 @@ #ifndef KIM_UI_GUI_PRIVATE_H #define KIM_UI_GUI_PRIVATE_H +#ifndef LEAN_CLIENT + #include struct kim_ui_gui_context; @@ -35,6 +37,9 @@ 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_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); @@ -42,6 +47,7 @@ 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, @@ -54,15 +60,17 @@ kim_error kim_ui_gui_change_password (kim_ui_gui_context in_context, char **out_new_password, char **out_verify_password); -kim_error kim_ui_gui_display_error (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); -void kim_ui_gui_free_string (kim_ui_gui_context in_context, - char *io_string); +void kim_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); +#endif /* LEAN_CLIENT */ + #endif /* KIM_UI_GUI_PRIVATE_H */ diff --git a/src/kim/lib/kim_ui_plugin.c b/src/kim/lib/kim_ui_plugin.c index 5c5cc26eb..f1b5db923 100644 --- a/src/kim/lib/kim_ui_plugin.c +++ b/src/kim/lib/kim_ui_plugin.c @@ -156,6 +156,24 @@ kim_error kim_ui_plugin_init (kim_ui_plugin_context *out_context) /* ------------------------------------------------------------------------ */ +kim_error kim_ui_plugin_enter_identity (kim_ui_plugin_context in_context, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = in_context->ftable->enter_identity (in_context->plugin_context, + out_identity); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_ui_plugin_select_identity (kim_ui_plugin_context in_context, kim_selection_hints in_hints, kim_identity *out_identity) @@ -180,6 +198,7 @@ kim_error kim_ui_plugin_select_identity (kim_ui_plugin_context in_context, kim_error kim_ui_plugin_auth_prompt (kim_ui_plugin_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, @@ -196,6 +215,7 @@ kim_error kim_ui_plugin_auth_prompt (kim_ui_plugin_context in_context, err = in_context->ftable->auth_prompt (in_context->plugin_context, in_identity, in_type, + in_hide_reply, in_title, in_message, in_description, @@ -236,11 +256,11 @@ kim_error kim_ui_plugin_change_password (kim_ui_plugin_context in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_ui_plugin_display_error (kim_ui_plugin_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description) +kim_error kim_ui_plugin_handle_error (kim_ui_plugin_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; @@ -249,11 +269,11 @@ kim_error kim_ui_plugin_display_error (kim_ui_plugin_context in_context, if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - err = in_context->ftable->display_error (in_context->plugin_context, - in_identity, - in_error, - in_error_message, - in_error_description); + err = in_context->ftable->handle_error (in_context->plugin_context, + in_identity, + in_error, + in_error_message, + in_error_description); } return check_error (err); @@ -261,8 +281,8 @@ kim_error kim_ui_plugin_display_error (kim_ui_plugin_context in_context, /* ------------------------------------------------------------------------ */ -void kim_ui_plugin_free_string (kim_ui_plugin_context in_context, - char *io_string) +void kim_ui_plugin_free_string (kim_ui_plugin_context in_context, + char **io_string) { kim_error err = KIM_NO_ERROR; diff --git a/src/kim/lib/kim_ui_plugin_private.h b/src/kim/lib/kim_ui_plugin_private.h index b48166516..c39447df0 100644 --- a/src/kim/lib/kim_ui_plugin_private.h +++ b/src/kim/lib/kim_ui_plugin_private.h @@ -35,6 +35,9 @@ typedef struct kim_ui_plugin_context *kim_ui_plugin_context; kim_error kim_ui_plugin_init (kim_ui_plugin_context *out_context); +kim_error kim_ui_plugin_enter_identity (kim_ui_plugin_context in_context, + kim_identity *out_identity); + kim_error kim_ui_plugin_select_identity (kim_ui_plugin_context in_context, kim_selection_hints in_hints, kim_identity *out_identity); @@ -42,6 +45,7 @@ kim_error kim_ui_plugin_select_identity (kim_ui_plugin_context in_context, kim_error kim_ui_plugin_auth_prompt (kim_ui_plugin_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, @@ -54,14 +58,14 @@ kim_error kim_ui_plugin_change_password (kim_ui_plugin_context in_context, char **out_new_password, char **out_verify_password); -kim_error kim_ui_plugin_display_error (kim_ui_plugin_context in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description); +kim_error kim_ui_plugin_handle_error (kim_ui_plugin_context in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); -void kim_ui_plugin_free_string (kim_ui_plugin_context in_context, - char *io_string); +void kim_ui_plugin_free_string (kim_ui_plugin_context in_context, + char **io_string); kim_error kim_ui_plugin_fini (kim_ui_plugin_context *io_context); diff --git a/src/kim/lib/kim_ui_private.h b/src/kim/lib/kim_ui_private.h index 21183ef2b..817a4b29f 100644 --- a/src/kim/lib/kim_ui_private.h +++ b/src/kim/lib/kim_ui_private.h @@ -36,22 +36,41 @@ enum kim_ui_type { kim_ui_type_none }; +enum kim_ui_error_type { + kim_ui_error_type_authentication, + kim_ui_error_type_change_password, + kim_ui_error_type_selection, + kim_ui_error_type_generic +}; + /* declare struct on stack. Deep contents will be freed by kim_ui_fini. */ typedef struct kim_ui_context { enum kim_ui_type type; void *tcontext; + 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); +kim_error kim_ui_enter_identity (kim_ui_context *in_context, + kim_identity *out_identity); + kim_error kim_ui_select_identity (kim_ui_context *in_context, kim_selection_hints in_hints, - kim_identity *out_identity); + 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, @@ -64,14 +83,20 @@ kim_error kim_ui_change_password (kim_ui_context *in_context, char **out_new_password, char **out_verify_password); -kim_error kim_ui_display_error (kim_ui_context *in_context, - kim_identity in_identity, - kim_error in_error, - kim_string in_error_message, - kim_string in_error_description); +/* Helper function */ +kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, + kim_identity in_identity, + enum kim_ui_error_type in_type, + kim_error in_error); + +kim_error kim_ui_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); void kim_ui_free_string (kim_ui_context *in_context, - char *io_string); + char **io_string); kim_error kim_ui_fini (kim_ui_context *io_context); diff --git a/src/kim/lib/mac/kim_os_library.c b/src/kim/lib/mac/kim_os_library.c index 43dd3d5c7..4abe13e20 100644 --- a/src/kim/lib/mac/kim_os_library.c +++ b/src/kim/lib/mac/kim_os_library.c @@ -95,6 +95,7 @@ kim_error kim_os_library_unlock_for_bundle_lookup (void) kim_ui_environment kim_os_library_get_ui_environment (void) { +#ifndef LEAN_CLIENT kipc_session_attributes_t attributes = kipc_session_get_attributes (); if (attributes & kkipc_session_caller_uses_gui) { @@ -106,6 +107,7 @@ kim_ui_environment kim_os_library_get_ui_environment (void) } kim_debug_printf ("kim_os_library_get_ui_environment(): no way to talk to the user."); +#endif return KIM_UI_ENVIRONMENT_NONE; } diff --git a/src/kim/lib/mac/kim_os_string.c b/src/kim/lib/mac/kim_os_string.c index 9cd8e0559..fab5ed8fe 100644 --- a/src/kim/lib/mac/kim_os_string.c +++ b/src/kim/lib/mac/kim_os_string.c @@ -33,8 +33,7 @@ static kim_error kim_os_string_for_key_in_bundle (CFBundleRef in_bundle, CFStringRef in_key, kim_string *out_string) { - kim_error lock_err = kim_os_library_lock_for_bundle_lookup (); - kim_error err = lock_err; + kim_error err = KIM_NO_ERROR; kim_string string = NULL; if (!err && !in_bundle ) { err = check_error (KIM_NULL_PARAMETER_ERR); } @@ -100,9 +99,7 @@ static kim_error kim_os_string_for_key_in_bundle (CFBundleRef in_bundle, } kim_string_free (&string); - - if (!lock_err) { kim_os_library_unlock_for_bundle_lookup (); } - + return check_error (err); } @@ -110,10 +107,40 @@ static kim_error kim_os_string_for_key_in_bundle (CFBundleRef in_bundle, /* ------------------------------------------------------------------------ */ +kim_error kim_os_string_create_localized (kim_string *out_string, + kim_string in_string) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_create_for_key (&string, in_string); + } + + if (!err && !string) { + err = kim_string_copy (&string, in_string); + } + + if (!err) { + *out_string = string; + string = NULL; + } + + kim_string_free (&string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_os_string_create_for_key (kim_string *out_string, kim_string in_key_string) { - kim_error err = KIM_NO_ERROR; + kim_error lock_err = kim_os_library_lock_for_bundle_lookup (); + kim_error err = lock_err; CFStringRef key = NULL; kim_string string = NULL; @@ -148,6 +175,8 @@ kim_error kim_os_string_create_for_key (kim_string *out_string, kim_string_free (&string); if (key) { CFRelease (key); } + if (!lock_err) { kim_os_library_unlock_for_bundle_lookup (); } + return check_error (err); } @@ -222,6 +251,7 @@ kim_error kim_os_string_get_cfstring (kim_string in_string, kim_error kim_os_string_compare (kim_string in_string, kim_string in_compare_to_string, + kim_boolean in_case_insensitive, kim_comparison *out_comparison) { kim_error err = KIM_NO_ERROR; @@ -243,8 +273,13 @@ kim_error kim_os_string_compare (kim_string in_string, } if (!err) { + CFOptionFlags options = (in_case_insensitive ? + 1 : kCFCompareCaseInsensitive); + /* Returned CFComparisonResult is compatible with kim_comparison_t */ - *out_comparison = CFStringCompare (cfstring, compare_to_cfstring, 0); + *out_comparison = CFStringCompare (cfstring, + compare_to_cfstring, + options); } if (cfstring ) { CFRelease (cfstring); } -- 2.26.2