Return to osx_attr_handler.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / osx_attr |
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: }