Annotation of embedaddon/strongswan/src/libcharon/plugins/osx_attr/osx_attr_handler.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2013 Martin Willi
        !             3:  * Copyright (C) 2013 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "osx_attr_handler.h"
        !            17: 
        !            18: #include <networking/host.h>
        !            19: #include <utils/debug.h>
        !            20: 
        !            21: #include <SystemConfiguration/SCDynamicStore.h>
        !            22: 
        !            23: typedef struct private_osx_attr_handler_t private_osx_attr_handler_t;
        !            24: 
        !            25: /**
        !            26:  * Private data of an osx_attr_handler_t object.
        !            27:  */
        !            28: struct private_osx_attr_handler_t {
        !            29: 
        !            30:        /**
        !            31:         * Public interface
        !            32:         */
        !            33:        osx_attr_handler_t public;
        !            34: 
        !            35:        /**
        !            36:         * Backup of original DNS servers, before we mess with it
        !            37:         */
        !            38:        CFMutableArrayRef original;
        !            39: 
        !            40:        /**
        !            41:         * Append DNS servers to existing entries, instead of replacing
        !            42:         */
        !            43:        bool append;
        !            44: };
        !            45: 
        !            46: /**
        !            47:  * Create a path to the DNS configuration of the Primary IPv4 Service
        !            48:  */
        !            49: static CFStringRef create_dns_path(SCDynamicStoreRef store)
        !            50: {
        !            51:        CFStringRef service, path = NULL;
        !            52:        CFDictionaryRef dict;
        !            53: 
        !            54:        /* get primary service */
        !            55:        dict = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));
        !            56:        if (dict)
        !            57:        {
        !            58:                service = CFDictionaryGetValue(dict, CFSTR("PrimaryService"));
        !            59:                if (service)
        !            60:                {
        !            61:                        path = CFStringCreateWithFormat(NULL, NULL,
        !            62:                                                                CFSTR("State:/Network/Service/%@/DNS"), service);
        !            63:                }
        !            64:                else
        !            65:                {
        !            66:                        DBG1(DBG_CFG, "SystemConfiguration PrimaryService not known");
        !            67:                }
        !            68:                CFRelease(dict);
        !            69:        }
        !            70:        else
        !            71:        {
        !            72:                DBG1(DBG_CFG, "getting global IPv4 SystemConfiguration failed");
        !            73:        }
        !            74:        return path;
        !            75: }
        !            76: 
        !            77: /**
        !            78:  * Create a mutable dictionary from path, a new one if not found
        !            79:  */
        !            80: static CFMutableDictionaryRef get_dictionary(SCDynamicStoreRef store,
        !            81:                                                                                         CFStringRef path)
        !            82: {
        !            83:        CFDictionaryRef dict;
        !            84:        CFMutableDictionaryRef mut = NULL;
        !            85: 
        !            86:        dict = SCDynamicStoreCopyValue(store, path);
        !            87:        if (dict)
        !            88:        {
        !            89:                if (CFGetTypeID(dict) == CFDictionaryGetTypeID())
        !            90:                {
        !            91:                        mut = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        !            92:                }
        !            93:                CFRelease(dict);
        !            94:        }
        !            95:        if (!mut)
        !            96:        {
        !            97:                mut = CFDictionaryCreateMutable(NULL, 0,
        !            98:                                                                                &kCFTypeDictionaryKeyCallBacks,
        !            99:                                                                                &kCFTypeDictionaryValueCallBacks);
        !           100:        }
        !           101:        return mut;
        !           102: }
        !           103: 
        !           104: /**
        !           105:  * Create a mutable array from dictionary path, a new one if not found
        !           106:  */
        !           107: static CFMutableArrayRef get_array_from_dict(CFDictionaryRef dict,
        !           108:                                                                                         CFStringRef name)
        !           109: {
        !           110:        CFArrayRef arr;
        !           111: 
        !           112:        arr = CFDictionaryGetValue(dict, name);
        !           113:        if (arr && CFGetTypeID(arr) == CFArrayGetTypeID())
        !           114:        {
        !           115:                return CFArrayCreateMutableCopy(NULL, 0, arr);
        !           116:        }
        !           117:        return CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        !           118: }
        !           119: 
        !           120: /**
        !           121:  * Add/Remove a DNS server to the configuration
        !           122:  */
        !           123: static bool manage_dns(private_osx_attr_handler_t *this,
        !           124:                                           int family, chunk_t data, bool add)
        !           125: {
        !           126:        SCDynamicStoreRef store;
        !           127:        CFStringRef path, dns;
        !           128:        CFMutableArrayRef arr;
        !           129:        CFMutableDictionaryRef dict;
        !           130:        CFIndex i;
        !           131:        host_t *server;
        !           132:        char buf[64];
        !           133:        bool success = FALSE;
        !           134: 
        !           135:        server = host_create_from_chunk(family, data, 0);
        !           136:        if (!server)
        !           137:        {
        !           138:                return FALSE;
        !           139:        }
        !           140:        snprintf(buf, sizeof(buf), "%H", server);
        !           141:        server->destroy(server);
        !           142: 
        !           143:        store = SCDynamicStoreCreate(NULL, CFSTR("osx-attr"), NULL, NULL);
        !           144:        path = create_dns_path(store);
        !           145:        if (path)
        !           146:        {
        !           147:                dict = get_dictionary(store, path);
        !           148:                arr = get_array_from_dict(dict, CFSTR("ServerAddresses"));
        !           149:                dns = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
        !           150:                if (add)
        !           151:                {
        !           152:                        if (!this->append && !this->original)
        !           153:                        {       /* backup original config, start with empty set */
        !           154:                                this->original = arr;
        !           155:                                arr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        !           156:                        }
        !           157:                        DBG1(DBG_CFG, "installing %s as DNS server", buf);
        !           158:                        CFArrayInsertValueAtIndex(arr, 0, dns);
        !           159:                }
        !           160:                else
        !           161:                {
        !           162:                        i = CFArrayGetFirstIndexOfValue(arr,
        !           163:                                                                        CFRangeMake(0, CFArrayGetCount(arr)), dns);
        !           164:                        if (i >= 0)
        !           165:                        {
        !           166:                                DBG1(DBG_CFG, "removing %s from DNS servers (%d)", buf, i);
        !           167:                                CFArrayRemoveValueAtIndex(arr, i);
        !           168:                        }
        !           169:                        if (!this->append && this->original && CFArrayGetCount(arr) == 0)
        !           170:                        {       /* restore original config */
        !           171:                                CFRelease(arr);
        !           172:                                arr = this->original;
        !           173:                                this->original = NULL;
        !           174:                        }
        !           175:                }
        !           176:                CFRelease(dns);
        !           177:                CFDictionarySetValue(dict, CFSTR("ServerAddresses"), arr);
        !           178:                CFRelease(arr);
        !           179: 
        !           180:                success = SCDynamicStoreSetValue(store, path, dict);
        !           181:                CFRelease(dict);
        !           182:                CFRelease(path);
        !           183:        }
        !           184:        CFRelease(store);
        !           185: 
        !           186:        if (!success)
        !           187:        {
        !           188:                DBG1(DBG_CFG, "adding DNS server to SystemConfiguration failed");
        !           189:        }
        !           190:        return success;
        !           191: }
        !           192: 
        !           193: METHOD(attribute_handler_t, handle, bool,
        !           194:        private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
        !           195:        configuration_attribute_type_t type, chunk_t data)
        !           196: {
        !           197:        switch (type)
        !           198:        {
        !           199:                case INTERNAL_IP4_DNS:
        !           200:                        return manage_dns(this, AF_INET, data, TRUE);
        !           201:                default:
        !           202:                        return FALSE;
        !           203:        }
        !           204: }
        !           205: 
        !           206: METHOD(attribute_handler_t, release, void,
        !           207:        private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
        !           208:        configuration_attribute_type_t type, chunk_t data)
        !           209: {
        !           210:        switch (type)
        !           211:        {
        !           212:                case INTERNAL_IP4_DNS:
        !           213:                        manage_dns(this, AF_INET, data, FALSE);
        !           214:                        break;
        !           215:                default:
        !           216:                        break;
        !           217:        }
        !           218: }
        !           219: 
        !           220: METHOD(enumerator_t, enumerate_dns, bool,
        !           221:        enumerator_t *this, va_list args)
        !           222: {
        !           223:        configuration_attribute_type_t *type;
        !           224:        chunk_t *data;
        !           225: 
        !           226:        VA_ARGS_VGET(args, type, data);
        !           227:        *type = INTERNAL_IP4_DNS;
        !           228:        *data = chunk_empty;
        !           229:        this->venumerate = (void*)return_false;
        !           230:        return TRUE;
        !           231: }
        !           232: 
        !           233: METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
        !           234:        private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
        !           235:        linked_list_t *vips)
        !           236: {
        !           237:        enumerator_t *enumerator;
        !           238: 
        !           239:        INIT(enumerator,
        !           240:                .enumerate = enumerator_enumerate_default,
        !           241:                .venumerate = _enumerate_dns,
        !           242:                .destroy = (void*)free,
        !           243:        );
        !           244:        return enumerator;
        !           245: }
        !           246: 
        !           247: METHOD(osx_attr_handler_t, destroy, void,
        !           248:        private_osx_attr_handler_t *this)
        !           249: {
        !           250:        free(this);
        !           251: }
        !           252: 
        !           253: /**
        !           254:  * See header
        !           255:  */
        !           256: osx_attr_handler_t *osx_attr_handler_create()
        !           257: {
        !           258:        private_osx_attr_handler_t *this;
        !           259: 
        !           260:        INIT(this,
        !           261:                .public = {
        !           262:                        .handler = {
        !           263:                                .handle = _handle,
        !           264:                                .release = _release,
        !           265:                                .create_attribute_enumerator = _create_attribute_enumerator,
        !           266:                        },
        !           267:                        .destroy = _destroy,
        !           268:                },
        !           269:                .append = lib->settings->get_bool(lib->settings,
        !           270:                                                                "%s.plugins.osx-attr.append", TRUE, lib->ns),
        !           271:        );
        !           272: 
        !           273:        return &this->public;
        !           274: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>