Annotation of embedaddon/strongswan/src/libcharon/plugins/osx_attr/osx_attr_handler.c, revision 1.1.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>