1/* 2 * Copyright (c) 2003-2008,2011,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 * print_cert.c 24 * 25 */ 26 27 28#include "print_cert.h" 29#include <CoreFoundation/CoreFoundation.h> 30#include <Security/SecCertificatePriv.h> 31#include <Security/SecTrustPriv.h> 32#include <utilities/SecIOFormat.h> 33#include <utilities/SecCFWrappers.h> 34 35 36static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { 37 CFIndex count = CFArrayGetCount(plist); 38 CFIndex ix; 39 for (ix = 0; ix < count ; ++ix) { 40 CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, 41 ix); 42 CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, 43 kSecPropertyKeyType); 44 CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, 45 kSecPropertyKeyLabel); 46 CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, 47 kSecPropertyKeyLocalizedLabel); 48 CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, 49 kSecPropertyKeyValue); 50 51 bool isSection = CFEqual(pType, kSecPropertyTypeSection); 52 CFMutableStringRef line = CFStringCreateMutable(NULL, 0); 53 CFIndex jx = 0; 54 for (jx = 0; jx < indent; ++jx) { 55 CFStringAppend(line, CFSTR(" ")); 56 } 57 if (llabel) { 58 CFStringAppend(line, llabel); 59 if (!isSection) { 60 for (jx = CFStringGetLength(llabel) + indent * 4; 61 jx < maxWidth; ++jx) { 62 CFStringAppend(line, CFSTR(" ")); 63 } 64 CFStringAppend(line, CFSTR(" : ")); 65 } 66 } 67 if (CFEqual(pType, kSecPropertyTypeWarning)) { 68 CFStringAppend(line, CFSTR("*WARNING* ")); 69 CFStringAppend(line, (CFStringRef)value); 70 } else if (CFEqual(pType, kSecPropertyTypeError)) { 71 CFStringAppend(line, CFSTR("*ERROR* ")); 72 CFStringAppend(line, (CFStringRef)value); 73 } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { 74 CFStringAppend(line, CFSTR("*OK* ")); 75 CFStringAppend(line, (CFStringRef)value); 76 } else if (CFEqual(pType, kSecPropertyTypeTitle)) { 77 CFStringAppend(line, CFSTR("*")); 78 CFStringAppend(line, (CFStringRef)value); 79 CFStringAppend(line, CFSTR("*")); 80 } else if (CFEqual(pType, kSecPropertyTypeSection)) { 81 } else if (CFEqual(pType, kSecPropertyTypeData)) { 82 CFDataRef data = (CFDataRef)value; 83 CFIndex length = CFDataGetLength(data); 84 if (length > 20) 85 CFStringAppendFormat(line, NULL, CFSTR("[%" PRIdCFIndex " bytes] "), length); 86 const UInt8 *bytes = CFDataGetBytePtr(data); 87 for (jx = 0; jx < length; ++jx) { 88 if (jx == 0) 89 CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); 90 else if (jx < 15 || length <= 20) 91 CFStringAppendFormat(line, NULL, CFSTR(" %02X"), 92 bytes[jx]); 93 else { 94 CFStringAppend(line, CFSTR(" ...")); 95 break; 96 } 97 } 98 } else if (CFEqual(pType, kSecPropertyTypeString)) { 99 CFStringAppend(line, (CFStringRef)value); 100 } else if (CFEqual(pType, kSecPropertyTypeDate)) { 101 CFDateRef date = (CFDateRef)value; 102 CFLocaleRef lc = CFLocaleCopyCurrent(); 103 CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle); 104 CFStringRef ds; 105 if (df) { 106 CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0); 107 CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); 108 CFRelease(tz); 109 ds = CFDateFormatterCreateStringWithDate(NULL, df, date); 110 CFRelease(df); 111 } else { 112 ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date)); 113 } 114 CFStringAppend(line, ds); 115 CFRelease(ds); 116 CFRelease(lc); 117 } else if (CFEqual(pType, kSecPropertyTypeURL)) { 118 CFURLRef url = (CFURLRef)value; 119 CFStringAppend(line, CFSTR("<")); 120 CFStringAppend(line, CFURLGetString(url)); 121 CFStringAppend(line, CFSTR(">")); 122 } else { 123 CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), 124 pType, value); 125 } 126 127 if (!isSection || label) 128 CFStringWriteToFileWithNewline(line, stdout); 129 CFRelease(line); 130 if (isSection) { 131 printPlist((CFArrayRef)value, indent + 1, maxWidth); 132 } 133 } 134} 135 136static CFIndex maxLabelWidth(CFArrayRef plist, CFIndex indent) { 137 CFIndex count = CFArrayGetCount(plist); 138 CFIndex ix; 139 CFIndex maxWidth = 0; 140 for (ix = 0; ix < count ; ++ix) { 141 CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, 142 ix); 143 CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, 144 kSecPropertyKeyType); 145 CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, 146 kSecPropertyKeyLocalizedLabel); 147 CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, 148 kSecPropertyKeyValue); 149 150 if (CFEqual(pType, kSecPropertyTypeSection)) { 151 CFIndex width = maxLabelWidth((CFArrayRef)value, indent + 1); 152 if (width > maxWidth) 153 maxWidth = width; 154 } else if (llabel) { 155 CFIndex width = indent * 4 + CFStringGetLength(llabel); 156 if (width > maxWidth) 157 maxWidth = width; 158 } 159 } 160 161 return maxWidth; 162} 163 164void print_plist(CFArrayRef plist) { 165 if (plist) 166 printPlist(plist, 0, maxLabelWidth(plist, 0)); 167 else 168 printf("NULL plist\n"); 169} 170 171void print_cert(SecCertificateRef cert, bool verbose) { 172 CFArrayRef plist; 173 if (verbose) 174 plist = SecCertificateCopyProperties(cert); 175 else { 176 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 177 plist = SecCertificateCopySummaryProperties(cert, now); 178 } 179 180 CFStringRef subject = SecCertificateCopySubjectString(cert); 181 if (subject) { 182 CFStringWriteToFileWithNewline(subject, stdout); 183 CFRelease(subject); 184 } else { 185 CFStringWriteToFileWithNewline(CFSTR("no subject"), stdout); 186 } 187 188 print_plist(plist); 189 CFRelease(plist); 190} 191