From 39d15dde67fbc2f4c637e352a83d6e774c04154b Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 2 May 2013 10:36:37 +0200 Subject: [PATCH] xpc: ask App for passwords using connection specific channel --- src/frontends/osx/charon-xpc/xpc_channels.c | 90 +++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/frontends/osx/charon-xpc/xpc_channels.c b/src/frontends/osx/charon-xpc/xpc_channels.c index e8eb22551..fc03ab333 100644 --- a/src/frontends/osx/charon-xpc/xpc_channels.c +++ b/src/frontends/osx/charon-xpc/xpc_channels.c @@ -15,6 +15,7 @@ #include "xpc_channels.h" +#include #include #include #include @@ -40,6 +41,11 @@ struct private_xpc_channels_t { * Lock for channels list */ rwlock_t *lock; + + /** + * Callback credential set for passwords + */ + callback_cred_t *creds; }; /** @@ -50,6 +56,8 @@ typedef struct { xpc_connection_t conn; /* associated IKE_SA unique identifier */ uintptr_t sa; + /* did we already ask for a password? */ + bool passworded; } entry_t; /** @@ -185,12 +193,90 @@ METHOD(listener_t, ike_updown, bool, return TRUE; } +/** + * Query password from App using XPC channel + */ +static shared_key_t *query_password(xpc_connection_t conn, identification_t *id) +{ + char buf[128], *password; + xpc_object_t request, response; + shared_key_t *shared = NULL; + + request = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(request, "type", "rpc"); + xpc_dictionary_set_string(request, "rpc", "get_password"); + snprintf(buf, sizeof(buf), "%Y", id); + xpc_dictionary_set_string(request, "username", buf); + + response = xpc_connection_send_message_with_reply_sync(conn, request); + xpc_release(request); + if (xpc_get_type(response) == XPC_TYPE_DICTIONARY) + { + password = (char*)xpc_dictionary_get_string(response, "password"); + shared = shared_key_create(SHARED_EAP, + chunk_clone(chunk_from_str(password))); + } + xpc_release(response); + return shared; +} + +/** + * Password query callback + */ +static shared_key_t* password_cb(private_xpc_channels_t *this, + shared_key_type_t type, + identification_t *me, identification_t *other, + id_match_t *match_me, id_match_t *match_other) +{ + shared_key_t *shared = NULL; + ike_sa_t *ike_sa; + entry_t *entry; + u_int32_t sa; + + switch (type) + { + case SHARED_EAP: + break; + default: + return NULL; + } + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa) + { + sa = ike_sa->get_unique_id(ike_sa); + this->lock->read_lock(this->lock); + entry = this->channels->get(this->channels, (void*)sa); + if (entry && !entry->passworded) + { + entry->passworded = TRUE; + + shared = query_password(entry->conn, me); + if (shared) + { + if (match_me) + { + *match_me = ID_MATCH_PERFECT; + } + if (match_other) + { + *match_other = ID_MATCH_PERFECT; + } + } + } + this->lock->unlock(this->lock); + } + return shared; +} + METHOD(xpc_channels_t, destroy, void, private_xpc_channels_t *this) { enumerator_t *enumerator; entry_t *entry; + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + this->creds->destroy(this->creds); + enumerator = this->channels->create_enumerator(this->channels); while (enumerator->enumerate(enumerator, NULL, &entry)) { @@ -224,5 +310,9 @@ xpc_channels_t *xpc_channels_create() .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); + this->creds = callback_cred_create_shared( + (callback_cred_shared_cb_t)password_cb, this); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); + return &this->public; }