SecXPCError.c
1 /* 2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25 #include <stdio.h> 26 27 #include <utilities/SecXPCError.h> 28 #include <utilities/SecCFError.h> 29 #include <utilities/SecCFWrappers.h> 30 #include <utilities/der_plist.h> 31 32 CFStringRef sSecXPCErrorDomain = CFSTR("com.apple.security.xpc"); 33 34 static const char* kDomainKey = "domain"; 35 static const char* kCodeKey = "code"; 36 static const char* kUserInfoKey = "userinfo"; 37 38 CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) 39 { 40 CFErrorRef result = NULL; 41 42 if (xpc_get_type(xpc_error) == XPC_TYPE_DICTIONARY) { 43 CFStringRef domain = NULL; 44 45 const char * domain_string = xpc_dictionary_get_string(xpc_error, kDomainKey); 46 if (domain_string != NULL) { 47 domain = CFStringCreateWithCString(kCFAllocatorDefault, domain_string, kCFStringEncodingUTF8); 48 } else { 49 domain = sSecXPCErrorDomain; 50 CFRetain(domain); 51 } 52 CFIndex code = (CFIndex) xpc_dictionary_get_int64(xpc_error, kCodeKey); 53 54 CFTypeRef user_info = NULL; 55 size_t size = 0; 56 const uint8_t *der = xpc_dictionary_get_data(xpc_error, kUserInfoKey, &size); 57 if (der) { 58 const uint8_t *der_end = der + size; 59 der = der_decode_plist(kCFAllocatorDefault, 60 &user_info, NULL, der, der_end); 61 if (der != der_end) 62 CFReleaseNull(user_info); 63 } 64 65 result = CFErrorCreate(NULL, domain, code, user_info); 66 67 CFReleaseSafe(user_info); 68 CFReleaseSafe(domain); 69 } else { 70 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &result, NULL, CFSTR("Remote error not dictionary!: %@"), xpc_error); 71 } 72 return result; 73 } 74 75 static void SecXPCDictionarySetCFString(xpc_object_t dict, const char *key, CFStringRef string) 76 { 77 CFStringPerformWithCString(string, ^(const char *utf8Str) { 78 xpc_dictionary_set_string(dict, key, utf8Str); 79 }); 80 } 81 82 xpc_object_t SecCreateXPCObjectWithCFError(CFErrorRef error) 83 { 84 xpc_object_t error_xpc = xpc_dictionary_create(NULL, NULL, 0); 85 86 SecXPCDictionarySetCFString(error_xpc, kDomainKey, CFErrorGetDomain(error)); 87 xpc_dictionary_set_int64(error_xpc, kCodeKey, CFErrorGetCode(error)); 88 89 CFDictionaryRef user_info = CFErrorCopyUserInfo(error); 90 size_t size = der_sizeof_plist(user_info, NULL); 91 if (size) { 92 uint8_t *der = malloc(size); 93 uint8_t *der_end = der + size; 94 uint8_t *der_start = der_encode_plist(user_info, NULL, der, der_end); 95 if (der_start) { 96 assert(der == der_start); 97 xpc_dictionary_set_data(error_xpc, kUserInfoKey, der_start, der_end - der_start); 98 } 99 free(der); 100 } 101 CFRelease(user_info); 102 103 return error_xpc; 104 }