summaryrefslogtreecommitdiffstats
path: root/src/kim/lib/mac
diff options
context:
space:
mode:
authorAlexandra Ellwood <lxs@mit.edu>2008-09-18 18:57:01 +0000
committerAlexandra Ellwood <lxs@mit.edu>2008-09-18 18:57:01 +0000
commit066a3a67affb47fdf3333c700ff98fe4b5911bc6 (patch)
tree960827a43ac51dbf18c91af50a2c90e8b83221a4 /src/kim/lib/mac
parent06c7016164303d69a96bb38743351004b0bf5d0a (diff)
downloadkrb5-066a3a67affb47fdf3333c700ff98fe4b5911bc6.tar.gz
krb5-066a3a67affb47fdf3333c700ff98fe4b5911bc6.tar.xz
krb5-066a3a67affb47fdf3333c700ff98fe4b5911bc6.zip
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
Diffstat (limited to 'src/kim/lib/mac')
-rw-r--r--src/kim/lib/mac/kim_os_identity.c152
1 files changed, 152 insertions, 0 deletions
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 <pwd.h>
#include <unistd.h>
+#include <Security/Security.h>
#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;