* \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure.
* \brief Get a display string of the non-realm components of an identity.
*/
-kim_error kim_identity_get_components (kim_identity in_identity,
- kim_string *out_components);
+kim_error kim_identity_get_components_string (kim_identity in_identity,
+ kim_string *out_components);
/*!
* \param in_identity an identity object.
kim_identity_get_display_string
kim_identity_get_realm
kim_identity_get_number_of_components
-kim_identity_get_components
+kim_identity_get_components_string
kim_identity_get_component_at_index
kim_identity_get_krb5_principal
kim_identity_change_password
kim_identity_get_realm
kim_identity_get_number_of_components
kim_identity_get_component_at_index
-kim_identity_get_components
+kim_identity_get_components_string
kim_identity_get_krb5_principal
kim_identity_change_password
kim_identity_free
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) {
- 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) {
krb5_creds creds;
kim_boolean free_creds = 0;
kim_count prompt_count;
+ krb5_principal principal = kim_identity_krb5_principal (in_identity);
+ krb5_get_init_creds_opt *opts = kim_options_init_cred_options (options);
+ char *service = kim_options_service_name (options);
+ kim_time start_time = kim_options_start_time (options);
/* set counter to zero so we can tell if we got prompted */
context.prompt_count = 0;
principal,
NULL,
kim_ui_prompter,
- &context, 0,
- (char *) service,
- init_cred_options));
+ &context,
+ start_time,
+ service,
+ opts));
prompt_count = context.prompt_count; /* remember if we got prompts */
if (!err) { free_creds = 1; }
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 (credential && principal) { krb5_free_principal (credential->context, principal); }
-
if (!err) {
*out_credential = credential;
credential = NULL;
}
- if (!in_options) { kim_options_free (&options); }
- kim_string_free (&service);
+ if (options != in_options) { kim_options_free (&options); }
kim_credential_free (&credential);
return check_error (err);
krb5_creds creds;
kim_boolean free_creds = FALSE;
krb5_principal principal = NULL;
- kim_time start_time = 0;
- kim_string service_name = NULL;
- krb5_get_init_creds_opt *init_cred_options = NULL;
+ kim_options options = in_options;
if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); }
err = krb5_error (NULL, krb5_init_context (&credential->context));
}
- if (!err) {
- kim_options options = in_options;
-
- if (!options) {
- err = kim_options_create (&options);
- }
-
- if (!err) {
- err = kim_options_get_start_time (options, &start_time);
- }
-
- if (!err) {
- err = kim_options_get_service_name (options, &service_name);
- }
-
- if (!err) {
- err = kim_options_get_init_cred_options (options,
- credential->context,
- &init_cred_options);
- }
-
- if (options != in_options) { kim_options_free (&options); }
+ if (!err && !options) {
+ err = kim_options_create (&options);
}
if (!err) {
}
if (!err) {
+ krb5_get_init_creds_opt *opts = kim_options_init_cred_options (options);
+ char *service = kim_options_service_name (options);
+ kim_time start_time = kim_options_start_time (options);
+
err = krb5_error (credential->context,
krb5_get_init_creds_keytab (credential->context,
&creds,
principal,
keytab,
start_time,
- (char *) service_name,
- init_cred_options));
+ service,
+ opts));
if (!err) { free_creds = TRUE; }
}
&credential->creds));
}
+ if (principal ) { krb5_free_principal (credential->context, principal); }
+
if (!err) {
*out_credential = credential;
credential = NULL;
}
- if (principal ) { krb5_free_principal (credential->context, principal); }
+ if (options != in_options) { kim_options_free (&options); }
if (free_creds) { krb5_free_cred_contents (credential->context, &creds); }
- kim_options_free_init_cred_options (credential->context, &init_cred_options);
- kim_string_free (&service_name);
kim_credential_free (&credential);
return check_error (err);
kim_credential credential = NULL;
kim_string realm = NULL;
kim_string service = NULL;
- krb5_principal principal = NULL;
kim_string service_format = "kadmin/changepw@%s";
if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_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) {
krb5_creds creds;
kim_boolean free_creds = 0;
+ krb5_principal principal = kim_identity_krb5_principal (in_identity);
krb5_get_init_creds_opt opts;
krb5_get_init_creds_opt_init (&opts);
if (free_creds) { krb5_free_cred_contents (credential->context, &creds); }
}
- if (principal) { krb5_free_principal (credential->context, principal); }
-
if (!err) {
*out_user_was_prompted = (in_ui_context->prompt_count > 0);
*out_credential = credential;
/* ------------------------------------------------------------------------ */
kim_error kim_credential_store (kim_credential in_credential,
- kim_identity in_client_identity,
+ kim_identity in_identity,
kim_ccache *out_ccache)
{
kim_error err = KIM_NO_ERROR;
- krb5_context context = NULL;
krb5_ccache k5ccache = NULL;
- kim_string type = NULL;
- krb5_principal client_principal = NULL;
kim_boolean destroy_ccache_on_error = FALSE;
- if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-
- if (!err) {
- err = krb5_error (NULL, krb5_init_context (&context));
- }
-
- if (!err) {
- err = kim_identity_get_krb5_principal (in_client_identity, context,
- &client_principal);
- }
+ if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
char *environment_ccache = getenv ("KRB5CCNAME");
if (environment_ccache) {
- err = krb5_error (context,
- krb5_cc_resolve (context, environment_ccache,
+ err = krb5_error (in_credential->context,
+ krb5_cc_resolve (in_credential->context,
+ environment_ccache,
&k5ccache));
} else {
kim_ccache ccache = NULL;
err = kim_ccache_create_from_client_identity (&ccache,
- in_client_identity);
+ in_identity);
if (!err) {
- err = kim_ccache_get_krb5_ccache (ccache, context, &k5ccache);
+ err = kim_ccache_get_krb5_ccache (ccache,
+ in_credential->context,
+ &k5ccache);
} else if (err == KIM_NO_SUCH_PRINCIPAL_ERR) {
/* Nothing to replace, create a new ccache */
- err = krb5_error (context,
- krb5_cc_new_unique (context, "API", NULL,
- &k5ccache));
+ err = krb5_error (in_credential->context,
+ krb5_cc_new_unique (in_credential->context,
+ "API", NULL, &k5ccache));
if (!err) { destroy_ccache_on_error = TRUE; }
}
}
if (!err) {
+ krb5_principal principal = kim_identity_krb5_principal (in_identity);
+
err = krb5_error (in_credential->context,
krb5_cc_initialize (in_credential->context,
- k5ccache, client_principal));
+ k5ccache, principal));
}
if (!err) {
}
if (!err && out_ccache) {
- err = kim_ccache_create_from_krb5_ccache (out_ccache, context, k5ccache);
+ err = kim_ccache_create_from_krb5_ccache (out_ccache,
+ in_credential->context,
+ k5ccache);
}
if (k5ccache) {
krb5_cc_close (in_credential->context, k5ccache);
}
}
- if (client_principal) { krb5_free_principal (context, client_principal); }
- if (context ) { krb5_free_context (context); }
- kim_string_free (&type);
return check_error (err);
}
{
kim_error err = KIM_NO_ERROR;
krb5_context scontext = NULL;
- krb5_principal service_principal = NULL;
krb5_keytab keytab = NULL;
if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); }
err = krb5_error (NULL, krb5_init_secure_context (&scontext));
}
- if (!err && in_service_identity) {
- err = kim_identity_get_krb5_principal (in_service_identity, scontext, &service_principal);
- }
-
if (in_keytab) {
err = krb5_error (scontext,
krb5_kt_resolve (scontext, in_keytab, &keytab));
}
if (!err) {
+ krb5_principal sprincipal = NULL;
krb5_verify_init_creds_opt options;
/* That's "no key == fail" not "no fail" >.< */
krb5_verify_init_creds_opt_init (&options);
krb5_verify_init_creds_opt_set_ap_req_nofail (&options, in_fail_if_no_service_key);
+ if (in_service_identity) {
+ sprincipal = kim_identity_krb5_principal (in_service_identity);
+ }
+
err = krb5_error (scontext,
- krb5_verify_init_creds (scontext, in_credential->creds,
- service_principal,
+ krb5_verify_init_creds (scontext,
+ in_credential->creds,
+ sprincipal,
keytab,
NULL /* don't store creds in ccache */,
&options));
- if (err && !service_principal && in_fail_if_no_service_key) {
+ if (err && !in_service_identity && in_fail_if_no_service_key) {
/* If the service principal wasn't specified but we are supposed to
* fail without a key we should walk the keytab trying to find one
* that succeeds. */
}
}
- if (keytab ) { krb5_kt_close (scontext, keytab); }
- if (service_principal) { krb5_free_principal (scontext, service_principal); }
- if (scontext ) { krb5_free_context (scontext); }
+ if (keytab ) { krb5_kt_close (scontext, keytab); }
+ if (scontext) { krb5_free_context (scontext); }
return check_error (err);
}
if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err && !in_krb5_principal) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_krb5_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ /* KLCreatePrincipalFromKerberos5Principal passes NULL in_krb5_context */
if (!err) {
err = kim_identity_allocate (&identity);
}
if (!err) {
- err = krb5_error (NULL, krb5_init_context (&identity->context));
+ if (in_krb5_context) {
+ err = krb5_error (in_krb5_context,
+ krb5_copy_context (in_krb5_context,
+ &identity->context));
+ } else {
+ err = krb5_error (NULL,
+ krb5_init_context (&identity->context));
+ }
}
if (!err) {
/* ------------------------------------------------------------------------ */
-kim_error kim_identity_get_components (kim_identity in_identity,
- kim_string *out_components)
+kim_error kim_identity_get_components_string (kim_identity in_identity,
+ kim_string *out_components)
{
kim_error err = KIM_NO_ERROR;
kim_string components = NULL;
if (!err && !out_krb5_principal) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
- err = krb5_error (in_identity->context,
- krb5_copy_principal (in_identity->context,
+ err = krb5_error (in_krb5_context,
+ krb5_copy_principal (in_krb5_context,
in_identity->principal,
out_krb5_principal));
}
/* ------------------------------------------------------------------------ */
+krb5_principal kim_identity_krb5_principal (kim_identity in_identity)
+{
+ if (in_identity) {
+ return in_identity->principal;
+ }
+ check_error (KIM_NULL_PARAMETER_ERR); /* log error */
+ return NULL;
+}
+
+/* ------------------------------------------------------------------------ */
+
kim_error kim_identity_is_tgt_service (kim_identity in_identity,
kim_boolean *out_is_tgt_service)
{
#include "kim_library_private.h"
#include "kim_ui_private.h"
+krb5_principal kim_identity_krb5_principal (kim_identity in_identity);
+
kim_error kim_identity_is_tgt_service (kim_identity in_identity,
kim_boolean *out_is_tgt_service);
kim_boolean in_old_password_expired,
kim_ui_context *in_ui_context);
+kim_error kim_os_identity_remove_saved_password (kim_identity in_identity);
+
#endif /* KIM_IDENTITY_PRIVATE_H */
kim_boolean proxiable;
kim_boolean addressless;
kim_string service_name;
+ krb5_context init_cred_context;
+ krb5_get_init_creds_opt *init_cred_options;
};
struct kim_options_opaque kim_options_initializer = {
kim_default_forwardable,
kim_default_proxiable,
kim_default_addressless,
+NULL,
+NULL,
NULL };
/* ------------------------------------------------------------------------ */
return check_error (err);
}
+#pragma mark -
+
/* ------------------------------------------------------------------------ */
-kim_error kim_options_get_init_cred_options (kim_options in_options,
- krb5_context in_context,
- krb5_get_init_creds_opt **out_init_cred_options)
+char *kim_options_service_name (kim_options in_options)
{
- kim_error err = KIM_NO_ERROR;
- krb5_get_init_creds_opt *init_cred_options;
- krb5_address **addresses = NULL;
-
- if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- 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) {
- krb5_get_init_creds_opt_alloc (in_context, &init_cred_options);
- }
-
- if (!err && in_options) {
- if (!in_options->addressless) {
- err = krb5_error (in_context,
- krb5_os_localaddr (in_context, &addresses));
- }
-
- 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 (in_options) {
+ return (char *) in_options->service_name;
}
-
- if (!err) {
- *out_init_cred_options = init_cred_options;
- init_cred_options = NULL;
+ check_error (KIM_NULL_PARAMETER_ERR); /* log bad options input */
+ return NULL;
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_time kim_options_start_time (kim_options in_options)
+{
+ if (in_options) {
+ return in_options->start_time;
}
-
- if (init_cred_options) { krb5_get_init_creds_opt_free (in_context, init_cred_options); }
- if (addresses ) { krb5_free_addresses (in_context, addresses); }
-
- return check_error (err);
+ check_error (KIM_NULL_PARAMETER_ERR); /* log bad options input */
+ return 0;
}
/* ------------------------------------------------------------------------ */
-kim_error kim_options_free_init_cred_options (krb5_context in_context,
- krb5_get_init_creds_opt **io_init_cred_options)
+krb5_get_init_creds_opt *kim_options_init_cred_options (kim_options in_options)
{
kim_error err = KIM_NO_ERROR;
+ krb5_address **addresses = NULL;
- if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- 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;
+ if (!err && !in_options->addressless) {
+ err = krb5_error (in_options->init_cred_context,
+ krb5_os_localaddr (in_options->init_cred_context,
+ &addresses));
}
- return check_error (err);
+ if (!err && !in_options->init_cred_context) {
+ err = krb5_error (NULL,
+ krb5_init_context (&in_options->init_cred_context));
+ }
+
+ if (!err && !in_options->init_cred_options) {
+ err = krb5_error (in_options->init_cred_context,
+ krb5_get_init_creds_opt_alloc (in_options->init_cred_context,
+ &in_options->init_cred_options));
+ }
+
+ if (!err) {
+ krb5_get_init_creds_opt_set_tkt_life (in_options->init_cred_options,
+ in_options->lifetime);
+ krb5_get_init_creds_opt_set_renew_life (in_options->init_cred_options,
+ in_options->renewable ? in_options->renewal_lifetime : 0);
+ krb5_get_init_creds_opt_set_forwardable (in_options->init_cred_options,
+ in_options->forwardable);
+ krb5_get_init_creds_opt_set_proxiable (in_options->init_cred_options,
+ in_options->proxiable);
+ krb5_get_init_creds_opt_set_address_list (in_options->init_cred_options,
+ addresses);
+ addresses = NULL;
+ }
+
+ if (addresses) { krb5_free_addresses (in_options->init_cred_context,
+ addresses); }
+
+ return !check_error (err) ? in_options->init_cred_options : NULL;
}
/* ------------------------------------------------------------------------ */
{
if (io_options && *io_options) {
kim_string_free (&(*io_options)->service_name);
+ if ((*io_options)->init_cred_context) {
+ if ((*io_options)->init_cred_options) {
+ if ((*io_options)->init_cred_options->address_list) {
+ krb5_free_addresses ((*io_options)->init_cred_context,
+ (*io_options)->init_cred_options->address_list);
+ }
+ krb5_get_init_creds_opt_free ((*io_options)->init_cred_context,
+ (*io_options)->init_cred_options);
+ }
+ krb5_free_context ((*io_options)->init_cred_context);
+ }
+
free (*io_options);
*io_options = NULL;
}
kim_error kim_options_create_empty (kim_options *out_options);
-kim_error kim_options_get_init_cred_options (kim_options in_options,
- krb5_context in_context,
- krb5_get_init_creds_opt **out_init_cred_options);
+krb5_get_init_creds_opt *kim_options_init_cred_options (kim_options in_options);
-kim_error kim_options_free_init_cred_options (krb5_context in_context,
- krb5_get_init_creds_opt **io_init_cred_options);
+char *kim_options_service_name (kim_options in_options);
+
+kim_time kim_options_start_time (kim_options in_options);
#endif /* KIM_OPTIONS_PRIVATE_H */
kim_error kim_string_create_from_format_va (kim_string *out_string,
kim_string in_format,
- va_list in_args);
+ va_list in_args);
kim_error kim_string_create_from_buffer (kim_string *out_string,
const char *in_buffer,
kim_count in_length);
-kim_error kim_string_prepend (kim_string *io_string,
- kim_string in_prefix);
-
-kim_error kim_string_append (kim_string *io_string,
- kim_string in_suffix);
-
/* 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,
if (!err && !out_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
- err = kim_identity_get_components (in_identity, &name);
+ err = kim_identity_get_components_string (in_identity, &name);
}
if (!err) {
if (!err && !in_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
- err = kim_identity_get_components (in_identity, &name);
+ err = kim_identity_get_components_string (in_identity, &name);
}
if (!err) {
attrInfo.tag = &tag;
attrInfo.format = &format;
- err = SecKeychainItemCopyAttributesAndData (itemRef, &attrInfo, NULL,
- &copiedAttrs, 0, NULL);
+ err = SecKeychainItemCopyAttributesAndData (itemRef, &attrInfo,
+ NULL, &copiedAttrs,
+ 0, NULL);
if (!err) {
/* Label format used by Apple patches */
/* ------------------------------------------------------------------------ */
+kim_error kim_os_identity_remove_saved_password (kim_identity in_identity)
+{
+ kim_error err = KIM_NO_ERROR;
+ kim_string realm = NULL;
+ kim_string name = NULL;
+
+ if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+
+ if (!err) {
+ err = kim_identity_get_components_string (in_identity, &name);
+ }
+
+ if (!err) {
+ err = kim_identity_get_realm (in_identity, &realm);
+ }
+
+ if (!err) {
+ SecKeychainItemRef itemRef = NULL;
+ UInt32 namelen = strlen (name);
+ UInt32 realmlen = strlen (realm);
+ void *buffer = NULL;
+ UInt32 length = 0;
+
+ err = SecKeychainFindGenericPassword (nil,
+ realmlen, realm,
+ namelen, name,
+ &length, &buffer,
+ &itemRef);
+
+ if (!err) {
+ err = SecKeychainItemDelete (itemRef);
+
+ } else if (err == errSecItemNotFound) {
+ err = KIM_NO_ERROR; /* No password not an error */
+ }
+
+ if (itemRef) { CFRelease (itemRef); }
+ }
+
+ if (name ) { kim_string_free (&name); }
+ if (realm) { kim_string_free (&realm); }
+
+ return check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
kim_error kim_os_identity_create_for_username (kim_identity *out_identity)
{
kim_error err = KIM_NO_ERROR;