diff options
author | Tobias Brunner <tobias@strongswan.org> | 2010-05-04 18:18:51 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2010-06-15 19:58:58 +0200 |
commit | c373f14947e3b6d69304b52e1e82637f9dbedbbf (patch) | |
tree | cefdcb400c2c32dd11236f28096409622ae912db /src | |
parent | 51a00fb275d846c63402f84ffd47d899a59deaef (diff) | |
download | strongswan-c373f14947e3b6d69304b52e1e82637f9dbedbbf.tar.bz2 strongswan-c373f14947e3b6d69304b52e1e82637f9dbedbbf.tar.xz |
Adding an Android specific credential set.
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/Android.mk | 1 | ||||
-rw-r--r-- | src/libcharon/plugins/android/Makefile.am | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/android/android_creds.c | 282 | ||||
-rw-r--r-- | src/libcharon/plugins/android/android_creds.h | 73 | ||||
-rw-r--r-- | src/libcharon/plugins/android/android_plugin.c | 11 |
5 files changed, 369 insertions, 1 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 99fe31f60..6ac8143de 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -106,6 +106,7 @@ credentials/credential_set.h LOCAL_SRC_FILES += $(call add_plugin, android) ifneq ($(call plugin_enabled, android)),) +LOCAL_C_INCLUDES += frameworks/base/cmds/keystore LOCAL_SHARED_LIBRARIES += libcutils endif diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am index dfac4738f..6d45b2fb2 100644 --- a/src/libcharon/plugins/android/Makefile.am +++ b/src/libcharon/plugins/android/Makefile.am @@ -13,7 +13,8 @@ endif libstrongswan_android_la_SOURCES = \ android_plugin.c android_plugin.h \ android_handler.c android_handler.h \ - android_logger.c android_logger.h + android_logger.c android_logger.h \ + android_creds.c android_creds.h libstrongswan_android_la_LDFLAGS = -module -avoid-version libstrongswan_android_la_LIBADD = -lcutils diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c new file mode 100644 index 000000000..d91686b77 --- /dev/null +++ b/src/libcharon/plugins/android/android_creds.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <keystore_get.h> + +#include "android_creds.h" + +#include <daemon.h> +#include <threading/rwlock.h> + +typedef struct private_android_creds_t private_android_creds_t; + +/** + * Private data of an android_creds_t object + */ +struct private_android_creds_t { + + /** + * Public interface + */ + android_creds_t public; + + /** + * List of trusted certificates, certificate_t* + */ + linked_list_t *certs; + + /** + * User name (ID) + */ + identification_t *user; + + /** + * User password + */ + char *pass; + + /** + * read/write lock + */ + rwlock_t *lock; + +}; + +/** + * Certificate enumerator data + */ +typedef struct { + private_android_creds_t *this; + key_type_t key; + identification_t *id; +} cert_data_t; + +/** + * Filter function for certificates enumerator + */ +static bool cert_filter(cert_data_t *data, certificate_t **in, + certificate_t **out) +{ + certificate_t *cert = *in; + public_key_t *public; + + public = cert->get_public_key(cert); + if (!public) + { + return FALSE; + } + if (data->key != KEY_ANY && public->get_type(public) != data->key) + { + public->destroy(public); + return FALSE; + } + if (data->id && data->id->get_type(data->id) == ID_KEY_ID && + public->has_fingerprint(public, data->id->get_encoding(data->id))) + { + public->destroy(public); + *out = cert; + return TRUE; + } + public->destroy(public); + if (data->id && !cert->has_subject(cert, data->id)) + { + return FALSE; + } + *out = cert; + return TRUE; +} + +/** + * Destroy certificate enumerator data + */ +static void cert_data_destroy(cert_data_t *this) +{ + this->this->lock->unlock(this->this->lock); + free(this); +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_android_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + if (cert == CERT_X509 || cert == CERT_ANY) + { + cert_data_t *data; + this->lock->read_lock(this->lock); + INIT(data, .this = this, .id = id, .key = key); + return enumerator_create_filter( + this->certs->create_enumerator(this->certs), + (void*)cert_filter, data, (void*)cert_data_destroy); + } + return NULL; +} + +/** + * Shared key enumerator implementation + */ +typedef struct { + enumerator_t public; + private_android_creds_t *this; + shared_key_t *key; + bool done; +} shared_enumerator_t; + +METHOD(enumerator_t, shared_enumerate, bool, + shared_enumerator_t *this, shared_key_t **key, id_match_t *me, + id_match_t *other) +{ + if (this->done) + { + return FALSE; + } + *key = this->key; + *me = ID_MATCH_PERFECT; + *other = ID_MATCH_ANY; + this->done = TRUE; + return TRUE; +} + +METHOD(enumerator_t, shared_destroy, void, + shared_enumerator_t *this) +{ + this->key->destroy(this->key); + this->this->lock->unlock(this->this->lock); + free(this); +} + +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_android_creds_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) +{ + shared_enumerator_t *enumerator; + + this->lock->read_lock(this->lock); + + if (!this->user || !this->pass) + { + this->lock->unlock(this->lock); + return NULL; + } + if (type != SHARED_EAP && type != SHARED_IKE) + { + this->lock->unlock(this->lock); + return NULL; + } + if (me && !me->equals(me, this->user)) + { + this->lock->unlock(this->lock); + return NULL; + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_shared_enumerate, + .destroy = _shared_destroy, + }, + .this = this, + .done = FALSE, + .key = shared_key_create(type, chunk_clone(chunk_create(this->pass, + strlen(this->pass)))), + ); + return &enumerator->public; +} + +METHOD(android_creds_t, add_certificate, bool, + private_android_creds_t *this, char *name) +{ + certificate_t *cert = NULL; + bool status = FALSE; + chunk_t chunk; + this->lock->write_lock(this->lock); + chunk.ptr = keystore_get(name, &chunk.len); + if (chunk.ptr) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_PEM, chunk, BUILD_END); + if (cert) + { + this->certs->insert_last(this->certs, cert); + status = TRUE; + } + free(chunk.ptr); + } + this->lock->unlock(this->lock); + return status; +} + +METHOD(android_creds_t, set_username_password, void, + private_android_creds_t *this, identification_t *id, char *password) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->user); + this->user = id->clone(id); + free(this->pass); + this->pass = password ? strdup(password) : NULL; + this->lock->unlock(this->lock); +} + +METHOD(android_creds_t, clear, void, + private_android_creds_t *this) +{ + certificate_t *cert; + this->lock->write_lock(this->lock); + while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS) + { + cert->destroy(cert); + } + DESTROY_IF(this->user); + free(this->pass); + this->user = NULL; + this->pass = NULL; + this->lock->unlock(this->lock); +} + +METHOD(android_creds_t, destroy, void, + private_android_creds_t *this) +{ + clear(this); + this->certs->destroy(this->certs); + this->lock->destroy(this->lock); + free(this); +} + +/** + * Described in header. + */ +android_creds_t *android_creds_create() +{ + private_android_creds_t *this; + + INIT(this, + .public = { + .set = { + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = _create_shared_enumerator, + .create_private_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .add_certificate = _add_certificate, + .set_username_password = _set_username_password, + .clear = _clear, + .destroy = _destroy, + }, + .certs = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/android/android_creds.h b/src/libcharon/plugins/android/android_creds.h new file mode 100644 index 000000000..0f7b8e0ea --- /dev/null +++ b/src/libcharon/plugins/android/android_creds.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup android_creds android_creds + * @{ @ingroup android + */ + +#ifndef ANDROID_CREDS_H_ +#define ANDROID_CREDS_H_ + +#include <credentials/credential_set.h> + +typedef struct android_creds_t android_creds_t; + +/** + * Android credentials helper. + */ +struct android_creds_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Add a trusted CA certificate from the Android keystore to serve by + * this set. + * + * @param name name/ID of the certificate in the keystore + * @return FALSE if the certificate does not exist or is invalid + */ + bool (*add_certificate)(android_creds_t *this, char *name); + + /** + * Set the username and password for authentication. + * + * @param id ID of the user + * @param password password to use for authentication + */ + void (*set_username_password)(android_creds_t *this, identification_t *id, + char *password); + + /** + * Clear the stored credentials. + */ + void (*clear)(android_creds_t *this); + + /** + * Destroy a android_creds instance. + */ + void (*destroy)(android_creds_t *this); + +}; + +/** + * Create an android_creds instance. + */ +android_creds_t *android_creds_create(); + +#endif /** ANDROID_CREDS_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c index 7f6c20fa2..a23ee7152 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android/android_plugin.c @@ -16,6 +16,7 @@ #include "android_plugin.h" #include "android_logger.h" #include "android_handler.h" +#include "android_creds.h" #include <hydra.h> #include <daemon.h> @@ -41,6 +42,12 @@ struct private_android_plugin_t { * Android specific DNS handler */ android_handler_t *handler; + + /** + * Android specific credential set + */ + android_creds_t *creds; + }; METHOD(plugin_t, destroy, void, @@ -48,7 +55,9 @@ METHOD(plugin_t, destroy, void, { hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); + charon->credentials->remove_set(charon->credentials, &this->creds->set); charon->bus->remove_listener(charon->bus, &this->logger->listener); + this->creds->destroy(this->creds); this->handler->destroy(this->handler); this->logger->destroy(this->logger); free(this); @@ -67,9 +76,11 @@ plugin_t *android_plugin_create() }, .logger = android_logger_create(), .handler = android_handler_create(), + .creds = android_creds_create(), ); charon->bus->add_listener(charon->bus, &this->logger->listener); + charon->credentials->add_set(charon->credentials, &this->creds->set); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); return &this->public.plugin; |