]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTool/sharedTool/print_cert.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / sharedTool / print_cert.c
diff --git a/SecurityTool/sharedTool/print_cert.c b/SecurityTool/sharedTool/print_cert.c
new file mode 100644 (file)
index 0000000..93a53f1
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2003-2008,2011,2013-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@
+ *
+ *  print_cert.c
+ *
+ */
+
+
+#include "print_cert.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecTrustPriv.h>
+#include <utilities/SecIOFormat.h>
+#include <utilities/SecCFWrappers.h>
+
+
+static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) {
+    CFIndex count = CFArrayGetCount(plist);
+    CFIndex ix;
+    for (ix = 0; ix < count ; ++ix) {
+        CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist,
+            ix);
+        CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyType);
+        CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyLabel);
+        CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyLocalizedLabel);
+        CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyValue);
+
+        bool isSection = CFEqual(pType, kSecPropertyTypeSection);
+        CFMutableStringRef line = CFStringCreateMutable(NULL, 0);
+        CFIndex jx = 0;
+        for (jx = 0; jx < indent; ++jx) {
+            CFStringAppend(line, CFSTR("    "));
+        }
+        if (llabel) {
+            CFStringAppend(line, llabel);
+            if (!isSection) {
+                for (jx = CFStringGetLength(llabel) + indent * 4;
+                    jx < maxWidth; ++jx) {
+                    CFStringAppend(line, CFSTR(" "));
+                }
+                CFStringAppend(line, CFSTR(" : "));
+            }
+        }
+        if (CFEqual(pType, kSecPropertyTypeWarning)) {
+            CFStringAppend(line, CFSTR("*WARNING* "));
+            CFStringAppend(line, (CFStringRef)value);
+        } else if (CFEqual(pType, kSecPropertyTypeError)) {
+            CFStringAppend(line, CFSTR("*ERROR* "));
+            CFStringAppend(line, (CFStringRef)value);
+        } else if (CFEqual(pType, kSecPropertyTypeSuccess)) {
+            CFStringAppend(line, CFSTR("*OK* "));
+            CFStringAppend(line, (CFStringRef)value);
+        } else if (CFEqual(pType, kSecPropertyTypeTitle)) {
+            CFStringAppend(line, CFSTR("*"));
+            CFStringAppend(line, (CFStringRef)value);
+            CFStringAppend(line, CFSTR("*"));
+        } else if (CFEqual(pType, kSecPropertyTypeSection)) {
+        } else if (CFEqual(pType, kSecPropertyTypeData)) {
+            CFDataRef data = (CFDataRef)value;
+            CFIndex length = CFDataGetLength(data);
+            if (length > 20)
+                CFStringAppendFormat(line, NULL, CFSTR("[%" PRIdCFIndex " bytes] "), length);
+            const UInt8 *bytes = CFDataGetBytePtr(data);
+            for (jx = 0; jx < length; ++jx) {
+                if (jx == 0)
+                    CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]);
+                else if (jx < 15 || length <= 20)
+                    CFStringAppendFormat(line, NULL, CFSTR(" %02X"),
+                        bytes[jx]);
+                else {
+                    CFStringAppend(line, CFSTR(" ..."));
+                    break;
+                }
+            }
+        } else if (CFEqual(pType, kSecPropertyTypeString)) {
+            CFStringAppend(line, (CFStringRef)value);
+        } else if (CFEqual(pType, kSecPropertyTypeDate)) {
+            CFDateRef date = (CFDateRef)value;
+            CFLocaleRef lc = CFLocaleCopyCurrent();
+            CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle);
+            CFStringRef ds;
+            if (df) {
+                CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0);
+                CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz);
+                CFRelease(tz);
+                ds = CFDateFormatterCreateStringWithDate(NULL, df, date);
+                CFRelease(df);
+            } else {
+                ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date));
+            }
+            CFStringAppend(line, ds);
+            CFRelease(ds);
+            CFRelease(lc);
+        } else if (CFEqual(pType, kSecPropertyTypeURL)) {
+            CFURLRef url = (CFURLRef)value;
+            CFStringAppend(line, CFSTR("<"));
+            CFStringAppend(line, CFURLGetString(url));
+            CFStringAppend(line, CFSTR(">"));
+        } else {
+            CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"),
+            pType, value);
+        }
+
+               if (!isSection || label)
+                       CFStringWriteToFileWithNewline(line, stdout);
+               CFRelease(line);
+        if (isSection) {
+            printPlist((CFArrayRef)value, indent + 1, maxWidth);
+        }
+    }
+}
+
+static CFIndex maxLabelWidth(CFArrayRef plist, CFIndex indent) {
+    CFIndex count = CFArrayGetCount(plist);
+    CFIndex ix;
+    CFIndex maxWidth = 0;
+    for (ix = 0; ix < count ; ++ix) {
+        CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist,
+            ix);
+        CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyType);
+        CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyLocalizedLabel);
+        CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop,
+            kSecPropertyKeyValue);
+
+        if (CFEqual(pType, kSecPropertyTypeSection)) {
+            CFIndex width = maxLabelWidth((CFArrayRef)value, indent + 1);
+            if (width > maxWidth)
+                maxWidth = width;
+        } else if (llabel) {
+            CFIndex width = indent * 4 + CFStringGetLength(llabel);
+            if (width > maxWidth)
+                maxWidth = width;
+        }
+    }
+
+    return maxWidth;
+}
+
+void print_plist(CFArrayRef plist) {
+    if (plist)
+        printPlist(plist, 0, maxLabelWidth(plist, 0));
+    else
+        printf("NULL plist\n");
+}
+
+void print_cert(SecCertificateRef cert, bool verbose) {
+#if TARGET_OS_IPHONE
+    CFArrayRef plist;
+    if (verbose)
+        plist = SecCertificateCopyProperties(cert);
+    else {
+        CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
+        plist = SecCertificateCopySummaryProperties(cert, now);
+    }
+
+    CFStringRef subject = SecCertificateCopySubjectString(cert);
+    if (subject) {
+        CFStringWriteToFileWithNewline(subject, stdout);
+        CFRelease(subject);
+    } else {
+        CFStringWriteToFileWithNewline(CFSTR("no subject"), stdout);
+    }
+
+    print_plist(plist);
+    CFReleaseSafe(plist);
+#else
+    (void)cert;
+    (void)verbose;
+#endif
+}