From: Martin Willi Date: Wed, 15 May 2013 13:56:17 +0000 (+0200) Subject: osx-attr: add plugin installing config attributes using SystemConfiguration X-Git-Tag: 5.1.0dr1~80^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45dcf4df575ba44879a0858a333938788406900b;p=thirdparty%2Fstrongswan.git osx-attr: add plugin installing config attributes using SystemConfiguration Currently installs DNS servers only, by prepending IP addresses to the DNS configuration of the primary networking service. --- diff --git a/configure.in b/configure.in index a89edb8794..696a179f49 100644 --- a/configure.in +++ b/configure.in @@ -225,6 +225,7 @@ ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.]) ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.]) ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.]) +ARG_ENABL_SET([osx-attr], [enable OS X SystemConfiguration attribute handler.]) ARG_ENABL_SET([android-dns], [enable Android specific DNS handler.]) ARG_ENABL_SET([android-log], [enable Android specific logger plugin.]) ARG_ENABL_SET([maemo], [enable Maemo specific plugin.]) @@ -1066,6 +1067,7 @@ ADD_PLUGIN([tnccs-dynamic], [c charon]) ADD_PLUGIN([medsrv], [c charon]) ADD_PLUGIN([medcli], [c charon]) ADD_PLUGIN([dhcp], [c charon]) +ADD_PLUGIN([osx-attr], [c charon cmd]) ADD_PLUGIN([android-dns], [c charon]) ADD_PLUGIN([android-log], [c charon]) ADD_PLUGIN([ha], [c charon]) @@ -1158,6 +1160,7 @@ AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue) AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue) AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue) AM_CONDITIONAL(USE_UCI, test x$uci = xtrue) +AM_CONDITIONAL(USE_OSX_ATTR, test x$osx_attr = xtrue) AM_CONDITIONAL(USE_ANDROID_DNS, test x$android_dns = xtrue) AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue) AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue) @@ -1435,6 +1438,7 @@ AC_CONFIG_FILES([ src/libcharon/plugins/duplicheck/Makefile src/libcharon/plugins/coupling/Makefile src/libcharon/plugins/radattr/Makefile + src/libcharon/plugins/osx_attr/Makefile src/libcharon/plugins/android_dns/Makefile src/libcharon/plugins/android_log/Makefile src/libcharon/plugins/maemo/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index ae7867f35d..32167e2c45 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -457,6 +457,13 @@ if MONOLITHIC endif endif +if USE_OSX_ATTR + SUBDIRS += plugins/osx_attr +if MONOLITHIC + libcharon_la_LIBADD += plugins/osx_attr/libstrongswan-osx-attr.la +endif +endif + if USE_ANDROID_DNS SUBDIRS += plugins/android_dns if MONOLITHIC diff --git a/src/libcharon/plugins/osx_attr/Makefile.am b/src/libcharon/plugins/osx_attr/Makefile.am new file mode 100644 index 0000000000..d1ceab41d2 --- /dev/null +++ b/src/libcharon/plugins/osx_attr/Makefile.am @@ -0,0 +1,18 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-osx-attr.la +else +plugin_LTLIBRARIES = libstrongswan-osx-attr.la +endif + +libstrongswan_osx_attr_la_SOURCES = \ + osx_attr_plugin.c osx_attr_plugin.h \ + osx_attr_handler.c osx_attr_handler.h + +libstrongswan_osx_attr_la_LDFLAGS = -module -avoid-version \ + -framework SystemConfiguration -framework CoreFoundation diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.c b/src/libcharon/plugins/osx_attr/osx_attr_handler.c new file mode 100644 index 0000000000..9a3b2701d8 --- /dev/null +++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 . + * + * 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 "osx_attr_handler.h" + +#include +#include + +#include + +typedef struct private_osx_attr_handler_t private_osx_attr_handler_t; + +/** + * Private data of an osx_attr_handler_t object. + */ +struct private_osx_attr_handler_t { + + /** + * Public interface + */ + osx_attr_handler_t public; +}; + +/** + * Create a path to the DNS configuration of the Primary IPv4 Service + */ +static CFStringRef create_dns_path(SCDynamicStoreRef store) +{ + CFStringRef service, path = NULL; + CFDictionaryRef dict; + + /* get primary service */ + dict = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4")); + if (dict) + { + service = CFDictionaryGetValue(dict, CFSTR("PrimaryService")); + if (service) + { + path = CFStringCreateWithFormat(NULL, NULL, + CFSTR("State:/Network/Service/%@/DNS"), service); + } + else + { + DBG1(DBG_CFG, "SystemConfiguration PrimaryService not known"); + } + CFRelease(dict); + } + else + { + DBG1(DBG_CFG, "getting global IPv4 SystemConfiguration failed"); + } + return path; +} + +/** + * Create a mutable dictionary from path, a new one if not found + */ +static CFMutableDictionaryRef get_dictionary(SCDynamicStoreRef store, + CFStringRef path) +{ + CFDictionaryRef dict; + CFMutableDictionaryRef mut = NULL; + + dict = SCDynamicStoreCopyValue(store, path); + if (dict) + { + if (CFGetTypeID(dict) == CFDictionaryGetTypeID()) + { + mut = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } + CFRelease(dict); + } + if (!mut) + { + mut = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + return mut; +} + +/** + * Create a mutable array from dictionary path, a new one if not found + */ +static CFMutableArrayRef get_array_from_dict(CFDictionaryRef dict, + CFStringRef name) +{ + CFArrayRef arr; + + arr = CFDictionaryGetValue(dict, name); + if (arr && CFGetTypeID(arr) == CFArrayGetTypeID()) + { + return CFArrayCreateMutableCopy(NULL, 0, arr); + } + return CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); +} + +/** + * Add/Remove a DNS server to the configuration + */ +static bool manage_dns(int family, chunk_t data, bool add) +{ + SCDynamicStoreRef store; + CFStringRef path, dns; + CFMutableArrayRef arr; + CFMutableDictionaryRef dict; + CFIndex i; + host_t *server; + char buf[64]; + bool success = FALSE; + + server = host_create_from_chunk(family, data, 0); + if (!server) + { + return FALSE; + } + snprintf(buf, sizeof(buf), "%H", server); + server->destroy(server); + + store = SCDynamicStoreCreate(NULL, CFSTR("osx-attr"), NULL, NULL); + path = create_dns_path(store); + if (path) + { + dict = get_dictionary(store, path); + arr = get_array_from_dict(dict, CFSTR("ServerAddresses")); + dns = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); + if (add) + { + DBG1(DBG_CFG, "installing %s as DNS server", buf); + CFArrayInsertValueAtIndex(arr, 0, dns); + } + else + { + i = CFArrayGetFirstIndexOfValue(arr, + CFRangeMake(0, CFArrayGetCount(arr)), dns); + if (i >= 0) + { + DBG1(DBG_CFG, "removing %s from DNS servers (%d)", buf, i); + CFArrayRemoveValueAtIndex(arr, i); + } + } + CFRelease(dns); + CFDictionarySetValue(dict, CFSTR("ServerAddresses"), arr); + CFRelease(arr); + + success = SCDynamicStoreSetValue(store, path, dict); + CFRelease(dict); + CFRelease(path); + } + CFRelease(store); + + if (!success) + { + DBG1(DBG_CFG, "adding DNS server to SystemConfiguration failed"); + } + return success; +} + +METHOD(attribute_handler_t, handle, bool, + private_osx_attr_handler_t *this, identification_t *id, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case INTERNAL_IP4_DNS: + return manage_dns(AF_INET, data, TRUE); + default: + return FALSE; + } +} + +METHOD(attribute_handler_t, release, void, + private_osx_attr_handler_t *this, identification_t *server, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case INTERNAL_IP4_DNS: + manage_dns(AF_INET, data, FALSE); + break; + default: + break; + } +} + +METHOD(enumerator_t, enumerate_dns, bool, + enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_DNS; + *data = chunk_empty; + /* stop enumeration */ + this->enumerate = (void*)return_false; + return TRUE; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, + private_osx_attr_handler_t *this, identification_t *id, + linked_list_t *vips) +{ + enumerator_t *enumerator; + + INIT(enumerator, + .enumerate = (void*)_enumerate_dns, + .destroy = (void*)free, + ); + return enumerator; +} + +METHOD(osx_attr_handler_t, destroy, void, + private_osx_attr_handler_t *this) +{ + free(this); +} + +/** + * See header + */ +osx_attr_handler_t *osx_attr_handler_create() +{ + private_osx_attr_handler_t *this; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = _release, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.h b/src/libcharon/plugins/osx_attr/osx_attr_handler.h new file mode 100644 index 0000000000..c1f979bcd0 --- /dev/null +++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 . + * + * 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 osx_attr_handler osx_attr_handler + * @{ @ingroup osx_attr + */ + +#ifndef OSX_ATTR_HANDLER_H_ +#define OSX_ATTR_HANDLER_H_ + +#include + +typedef struct osx_attr_handler_t osx_attr_handler_t; + +/** + * OS X specific attribute handler, using SystemConfiguration framework. + */ +struct osx_attr_handler_t { + + /** + * Implements attribute_handler_t. + */ + attribute_handler_t handler; + + /** + * Destroy a osx_attr_handler_t. + */ + void (*destroy)(osx_attr_handler_t *this); +}; + +/** + * Create an osx_attr_handler_t instance. + */ +osx_attr_handler_t *osx_attr_handler_create(); + +#endif /** OSX_ATTR_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/osx_attr/osx_attr_plugin.c b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c new file mode 100644 index 0000000000..380483c23e --- /dev/null +++ b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 . + * + * 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 "osx_attr_plugin.h" +#include "osx_attr_handler.h" + +#include +#include + +typedef struct private_osx_attr_plugin_t private_osx_attr_plugin_t; + +/** + * Private data of an osx_attr_plugin_t object. + */ +struct private_osx_attr_plugin_t { + + /** + * Public interface + */ + osx_attr_plugin_t public; + + /** + * Android specific DNS handler + */ + osx_attr_handler_t *handler; +}; + +METHOD(plugin_t, get_name, char*, + private_osx_attr_plugin_t *this) +{ + return "osx-attr"; +} + +/** + * Register handler + */ +static bool plugin_cb(private_osx_attr_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + hydra->attributes->add_handler(hydra->attributes, + &this->handler->handler); + } + else + { + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_osx_attr_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "osx-attr"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_osx_attr_plugin_t *this) +{ + this->handler->destroy(this->handler); + free(this); +} + +/** + * See header + */ +plugin_t *osx_attr_plugin_create() +{ + private_osx_attr_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .handler = osx_attr_handler_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/osx_attr/osx_attr_plugin.h b/src/libcharon/plugins/osx_attr/osx_attr_plugin.h new file mode 100644 index 0000000000..761379386d --- /dev/null +++ b/src/libcharon/plugins/osx_attr/osx_attr_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 . + * + * 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 osx_attr osx_attr + * @ingroup cplugins + * + * @defgroup osx_attr_plugin osx_attr_plugin + * @{ @ingroup osx_attr + */ + +#ifndef OSX_ATTR_PLUGIN_H_ +#define OSX_ATTR_PLUGIN_H_ + +#include + +typedef struct osx_attr_plugin_t osx_attr_plugin_t; + +/** + * Plugin providing an OS X specific configuration attribute handler. + */ +struct osx_attr_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** OSX_ATTR_PLUGIN_H_ @}*/