summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kim/lib/kim_identity.c85
-rw-r--r--src/kim/lib/kim_identity_private.h12
-rw-r--r--src/kim/lib/mac/kim_os_identity.c152
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)
@@ -471,32 +522,6 @@ kim_error kim_identity_get_krb5_principal (kim_identity in_identity,
}
/* ------------------------------------------------------------------------ */
-/*!
- * \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,
kim_boolean *out_is_tgt_service)
@@ -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 <kim/kim.h>
#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 <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;