From 066a3a67affb47fdf3333c700ff98fe4b5911bc6 Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Thu, 18 Sep 2008 18:57:01 +0000 Subject: [PATCH] Added functions to save and get password from keychain ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20732 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kim/lib/kim_identity.c | 85 +++++++++++----- src/kim/lib/kim_identity_private.h | 12 ++- src/kim/lib/mac/kim_os_identity.c | 152 +++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 27 deletions(-) diff --git a/src/kim/lib/kim_identity.c b/src/kim/lib/kim_identity.c index 2fd8579d0..e427a2a1b 100644 --- a/src/kim/lib/kim_identity.c +++ b/src/kim/lib/kim_identity.c @@ -450,6 +450,57 @@ kim_error kim_identity_get_component_at_index (kim_identity in_identity, /* ------------------------------------------------------------------------ */ +kim_error kim_identity_get_components (kim_identity in_identity, + kim_string *out_components) +{ + kim_error err = KIM_NO_ERROR; + kim_string components = NULL; + kim_count count, i; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_components) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_number_of_components (in_identity, &count); + } + + if (!err) { + err = kim_identity_get_component_at_index (in_identity, 0, &components); + } + + for (i = 1; !err && i < count; i++) { + kim_string new_components = NULL; + kim_string component = NULL; + + err = kim_identity_get_component_at_index (in_identity, 0, &component); + + if (!err) { + err = kim_string_create_from_format (&new_components, "%s/%s", + components, component); + } + + if (!err) { + kim_string_free (&components); + components = new_components; + new_components = NULL; + } + + if (component ) { kim_string_free (&component); } + if (new_components) { kim_string_free (&new_components); } + } + + if (!err) { + *out_components = components; + components = NULL; + } + + if (components) { kim_string_free (&components); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_identity_get_krb5_principal (kim_identity in_identity, krb5_context in_krb5_context, krb5_principal *out_krb5_principal) @@ -470,32 +521,6 @@ kim_error kim_identity_get_krb5_principal (kim_identity in_identity, return check_error (err); } -/* ------------------------------------------------------------------------ */ -/*! - * \param in_identity an identity object. - * \param out_gss_name on exit, a gss_name_t representation of \a in_identity. - * Must be freed with gss_release_name(). - * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. - * \brief Get the gss_name_t representation of an identity. - */ -/*kim_error kim_identity_get_gss_name (kim_identity in_identity, - gss_name_t *out_gss_name);*/ -/* -kim_error kim_identity_get_gss_name (kim_identity in_identity, - gss_name_t *out_gss_name) -{ - kim_error err = KIM_NO_ERROR; - - if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_gss_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } - - if (!err) { -#warning kim_identity_get_gss_name not implemented - } - - return check_error (err); -}*/ - /* ------------------------------------------------------------------------ */ kim_error kim_identity_is_tgt_service (kim_identity in_identity, @@ -528,6 +553,10 @@ kim_error kim_identity_change_password (kim_identity in_identity, if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err) { +#warning Implement change password GUI support + } + return check_error (err); } @@ -542,6 +571,10 @@ kim_error kim_identity_change_password_to_password (kim_identity in_identity, if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_new_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err) { +#warning Implement change password support + } + return check_error (err); } diff --git a/src/kim/lib/kim_identity_private.h b/src/kim/lib/kim_identity_private.h index 7bbbb7ce2..d22417955 100644 --- a/src/kim/lib/kim_identity_private.h +++ b/src/kim/lib/kim_identity_private.h @@ -30,9 +30,19 @@ #include #include "kim_library_private.h" -kim_error kim_os_identity_create_for_username (kim_identity *out_identity); +kim_error kim_identity_get_components (kim_identity in_identity, + kim_string *out_components); kim_error kim_identity_is_tgt_service (kim_identity in_identity, kim_boolean *out_is_tgt_service); + +kim_error kim_os_identity_create_for_username (kim_identity *out_identity); + +kim_error kim_os_identity_get_saved_password (kim_identity in_identity, + kim_string *out_password); + +kim_error kim_os_identity_set_saved_password (kim_identity in_identity, + kim_string in_password); + #endif /* KIM_IDENTITY_PRIVATE_H */ diff --git a/src/kim/lib/mac/kim_os_identity.c b/src/kim/lib/mac/kim_os_identity.c index 18e217660..c25729b75 100644 --- a/src/kim/lib/mac/kim_os_identity.c +++ b/src/kim/lib/mac/kim_os_identity.c @@ -26,11 +26,163 @@ #include #include +#include #include "kim_os_private.h" /* ------------------------------------------------------------------------ */ +kim_error kim_os_identity_get_saved_password (kim_identity in_identity, + kim_string *out_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string realm = NULL; + kim_string name = NULL; + void *buffer = NULL; + UInt32 length = 0; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_components (in_identity, &name); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + err = SecKeychainFindGenericPassword (nil, + strlen (realm), realm, + strlen (name), name, + &length, &buffer, + nil); + + if (!err && !buffer) { err = check_error (ENOENT); } + } + + if (!err) { + err = kim_string_create_from_buffer (out_password, buffer, length); + } + + if (name ) { kim_string_free (&name); } + if (realm ) { kim_string_free (&realm); } + if (buffer) { SecKeychainItemFreeContent (NULL, buffer); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_identity_set_saved_password (kim_identity in_identity, + kim_string in_password) +{ + 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 && !in_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_components (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); + + // Add the password to the keychain + err = SecKeychainAddGenericPassword (nil, + realmlen, realm, + namelen, name, + strlen (in_password), in_password, + &itemRef); + + if (err == errSecDuplicateItem) { + // We've already stored a password for this principal + // but it might have changed so update it + void *buffer = NULL; + UInt32 length = 0; + + err = SecKeychainFindGenericPassword (nil, + realmlen, realm, + namelen, name, + &length, &buffer, + &itemRef); + + if (!err) { + SecKeychainAttribute attrs[] = { + { kSecAccountItemAttr, namelen, (char *) name }, + { kSecServiceItemAttr, realmlen, (char *) realm } }; + UInt32 count = sizeof(attrs) / sizeof(attrs[0]); + const SecKeychainAttributeList attrList = { count, attrs }; + + err = SecKeychainItemModifyAttributesAndData (itemRef, + &attrList, + strlen (in_password), + in_password); + } + + } else if (!err) { + // We added a new entry, add a descriptive label + SecKeychainAttributeList *copiedAttrs = NULL; + SecKeychainAttributeInfo attrInfo; + UInt32 tag = 7; + UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING; + kim_string label = NULL; + + attrInfo.count = 1; + attrInfo.tag = &tag; + attrInfo.format = &format; + + err = SecKeychainItemCopyAttributesAndData (itemRef, &attrInfo, NULL, + &copiedAttrs, 0, NULL); + + if (!err) { + /* Label format used by Apple patches */ + err = kim_string_create_from_format (&label, "%s (%s)", + realm, name); + } + + if (!err) { + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + + /* Copy the tag they gave us and copy in our label */ + attr.tag = copiedAttrs->attr->tag; + attr.length = strlen (label); + attr.data = (char *) label; + + attrList.count = 1; + attrList.attr = &attr; + + /* And modify. */ + err = SecKeychainItemModifyAttributesAndData (itemRef, &attrList, + 0, NULL); + } + + if (label ) { kim_string_free (&label); } + if (copiedAttrs) { SecKeychainItemFreeAttributesAndData (copiedAttrs, NULL); } + } + + 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; -- 2.26.2