X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_transform/lib/misc.c diff --git a/Security/libsecurity_transform/lib/misc.c b/Security/libsecurity_transform/lib/misc.c new file mode 100644 index 00000000..54ac7848 --- /dev/null +++ b/Security/libsecurity_transform/lib/misc.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "misc.h" + + +// NOTE: the return may or allocate a fair bit more space then it needs. +// Use it for short lived conversions (or strdup the result). +char *utf8(CFStringRef s) { + CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1; + CFIndex used = 0; + UInt8 *buf = (UInt8 *)malloc(sz); + if (!buf) { + return NULL; + } + CFStringGetBytes(s, CFRangeMake(0, CFStringGetLength(s)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used); + buf[used] = 0; + + return (char*)buf; +} + +void CFfprintf(FILE *f, const char *format, ...) { + va_list ap; + va_start(ap, format); + + CFStringRef fmt = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); + CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, ap); + va_end(ap); + CFRelease(fmt); + + CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); + sz += 1; + CFIndex used = 0; + unsigned char *buf; + bool needs_free = false; + if (sz < 1024) { + buf = alloca(sz); + } else { + buf = malloc(sz); + needs_free = true; + } + if (buf) { + CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used); + } else { + buf = (unsigned char *)"malloc failue during CFfprintf\n"; + } + + fwrite(buf, 1, used, f); + if (needs_free) { + free(buf); + } + + CFRelease(str); +} + +CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description) { + const void *v_ekey = kCFErrorDescriptionKey; + const void *v_description = description; + CFErrorRef err = CFErrorCreateWithUserInfoKeysAndValues(NULL, domain, code, &v_ekey, &v_description, 1); + + return err; +} + +static +void add_t2ca(CFMutableDictionaryRef t2ca, CFStringRef t, CFStringRef a) { + CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, t); + if (!ca) { + ca = CFSetCreateMutable(NULL, 0, &kCFCopyStringSetCallBacks); + CFDictionarySetValue(t2ca, t, ca); + } + CFSetAddValue(ca, a); +} + +void CFSafeRelease(CFTypeRef object) { + if (object) { + CFRelease(object); + } +} + +void graphviz(FILE *f, SecTransformRef tr) { + CFDictionaryRef d = SecTransformCopyExternalRepresentation(tr); + + CFfprintf(f, "digraph TR {\n\tnode [shape=plaintext];\n\n"); + CFIndex i, j; + CFArrayRef transforms = CFDictionaryGetValue(d, CFSTR("TRANSFORMS")); + CFArrayRef connections = CFDictionaryGetValue(d, CFSTR("ARRAY")); + + + // map transforms to connected attributes + CFMutableDictionaryRef t2ca = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + for(i = 0; i < CFArrayGetCount(connections); i++) { + CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i); + + CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME")); + CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME")); + CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE")); + CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE")); + + add_t2ca(t2ca, t_from, a_from); + add_t2ca(t2ca, t_to, a_to); + } + + + for(i = 0; i < CFArrayGetCount(transforms); i++) { + CFDictionaryRef t = CFArrayGetValueAtIndex(transforms, i); + // NAME STATE(dict) TYPE + CFStringRef name = CFDictionaryGetValue(t, CFSTR("NAME")); + + CFfprintf(f, "\tsubgraph \"cluster_%@\"{\n", name); + + CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, name); + if (ca) { + CFIndex cnt = CFSetGetCount(ca); + CFStringRef *attrs = malloc(cnt * sizeof(CFStringRef)); + CFSetGetValues(ca, (const void **)attrs); + + for(j = 0; j < cnt; j++) { + CFfprintf(f, "\t\t\"%@#%@\" [label=\"%@\"];\n", name, attrs[j], attrs[j]); + } + CFfprintf(f, "\t\t\"%@\" [fontcolor=blue, fontsize=20];\n\t}\n"); + } + } + + CFfprintf(f, "\n"); + + for(i = 0; i < CFArrayGetCount(connections); i++) { + CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i); + + CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME")); + CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME")); + CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE")); + CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE")); + + CFfprintf(f, "\t\"%@#%@\" -> \"%@#%@\";\n", t_from, a_from, t_to, a_to); + } + + CFfprintf(f, "}\n"); + + CFfprintf(f, "\n/*\n%@\n/*\n", d); +}