]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/sslViewer/printCert.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / sslViewer / printCert.c
1 /*
2 * Copyright (c) 2003-2008,2011-2012,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 * printCert.c - utility functions for printing certificate info
26 */
27
28 #include "printCert.h"
29 #include <CoreFoundation/CoreFoundation.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecTrustPriv.h>
32
33 void fprint_string(CFStringRef string, FILE *file) {
34 UInt8 buf[256];
35 CFRange range = { .location = 0 };
36 range.length = CFStringGetLength(string);
37 while (range.length > 0) {
38 CFIndex bytesUsed = 0;
39 CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed);
40 fwrite(buf, 1, bytesUsed, file);
41 range.length -= converted;
42 range.location += converted;
43 }
44 }
45
46 void print_line(CFStringRef line) {
47 fprint_string(line, stdout);
48 fputc('\n', stdout);
49 }
50
51 static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) {
52 CFIndex count = CFArrayGetCount(plist);
53 CFIndex ix;
54 for (ix = 0; ix < count ; ++ix) {
55 CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist,
56 ix);
57 CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop,
58 kSecPropertyKeyType);
59 CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop,
60 kSecPropertyKeyLabel);
61 CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop,
62 kSecPropertyKeyLocalizedLabel);
63 CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop,
64 kSecPropertyKeyValue);
65
66 bool isSection = CFEqual(pType, kSecPropertyTypeSection);
67 CFMutableStringRef line = CFStringCreateMutable(NULL, 0);
68 CFIndex jx = 0;
69 for (jx = 0; jx < indent; ++jx) {
70 CFStringAppend(line, CFSTR(" "));
71 }
72 if (llabel) {
73 CFStringAppend(line, llabel);
74 if (!isSection) {
75 for (jx = CFStringGetLength(llabel) + indent * 4;
76 jx < maxWidth; ++jx) {
77 CFStringAppend(line, CFSTR(" "));
78 }
79 CFStringAppend(line, CFSTR(" : "));
80 }
81 }
82 if (CFEqual(pType, kSecPropertyTypeWarning)) {
83 CFStringAppend(line, CFSTR("*WARNING* "));
84 CFStringAppend(line, (CFStringRef)value);
85 } else if (CFEqual(pType, kSecPropertyTypeError)) {
86 CFStringAppend(line, CFSTR("*ERROR* "));
87 CFStringAppend(line, (CFStringRef)value);
88 } else if (CFEqual(pType, kSecPropertyTypeSuccess)) {
89 CFStringAppend(line, CFSTR("*OK* "));
90 CFStringAppend(line, (CFStringRef)value);
91 } else if (CFEqual(pType, kSecPropertyTypeTitle)) {
92 CFStringAppend(line, CFSTR("*"));
93 CFStringAppend(line, (CFStringRef)value);
94 CFStringAppend(line, CFSTR("*"));
95 } else if (CFEqual(pType, kSecPropertyTypeSection)) {
96 } else if (CFEqual(pType, kSecPropertyTypeData)) {
97 CFDataRef data = (CFDataRef)value;
98 CFIndex length = CFDataGetLength(data);
99 if (length > 20)
100 CFStringAppendFormat(line, NULL, CFSTR("[%d bytes] "), length);
101 const UInt8 *bytes = CFDataGetBytePtr(data);
102 for (jx = 0; jx < length; ++jx) {
103 if (jx == 0)
104 CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]);
105 else if (jx < 15 || length <= 20)
106 CFStringAppendFormat(line, NULL, CFSTR(" %02X"),
107 bytes[jx]);
108 else {
109 CFStringAppend(line, CFSTR(" ..."));
110 break;
111 }
112 }
113 } else if (CFEqual(pType, kSecPropertyTypeString)) {
114 CFStringAppend(line, (CFStringRef)value);
115 } else if (CFEqual(pType, kSecPropertyTypeDate)) {
116 CFDateRef date = (CFDateRef)value;
117 CFLocaleRef lc = CFLocaleCopyCurrent();
118 CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle);
119 CFStringRef ds;
120 if (df) {
121 CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0);
122 CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz);
123 CFRelease(tz);
124 ds = CFDateFormatterCreateStringWithDate(NULL, df, date);
125 CFRelease(df);
126 } else {
127 ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date));
128 }
129 CFStringAppend(line, ds);
130 CFRelease(ds);
131 CFRelease(lc);
132 } else if (CFEqual(pType, kSecPropertyTypeURL)) {
133 CFURLRef url = (CFURLRef)value;
134 CFStringAppend(line, CFSTR("<"));
135 CFStringAppend(line, CFURLGetString(url));
136 CFStringAppend(line, CFSTR(">"));
137 } else {
138 CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"),
139 pType, value);
140 }
141
142 if (!isSection || label)
143 print_line(line);
144 CFRelease(line);
145 if (isSection) {
146 printPlist((CFArrayRef)value, indent + 1, maxWidth);
147 }
148 }
149 }
150
151 static CFIndex maxLabelWidth(CFArrayRef plist, CFIndex indent) {
152 CFIndex count = CFArrayGetCount(plist);
153 CFIndex ix;
154 CFIndex maxWidth = 0;
155 for (ix = 0; ix < count ; ++ix) {
156 CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist,
157 ix);
158 CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop,
159 kSecPropertyKeyType);
160 CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop,
161 kSecPropertyKeyLocalizedLabel);
162 CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop,
163 kSecPropertyKeyValue);
164
165 if (CFEqual(pType, kSecPropertyTypeSection)) {
166 CFIndex width = maxLabelWidth((CFArrayRef)value, indent + 1);
167 if (width > maxWidth)
168 maxWidth = width;
169 } else if (llabel) {
170 CFIndex width = indent * 4 + CFStringGetLength(llabel);
171 if (width > maxWidth)
172 maxWidth = width;
173 }
174 }
175
176 return maxWidth;
177 }
178
179 void print_plist(CFArrayRef plist) {
180 if (plist)
181 printPlist(plist, 0, maxLabelWidth(plist, 0));
182 else
183 printf("NULL plist\n");
184 }
185
186 void print_cert(SecCertificateRef cert, bool verbose) {
187 // TODO: merge these when all SecCertificate APIs are present on both iOS and OS X
188 #if TARGET_OS_IOS
189 CFArrayRef plist;
190 if (verbose)
191 plist = SecCertificateCopyProperties(cert);
192 else {
193 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
194 plist = SecCertificateCopySummaryProperties(cert, now);
195 }
196
197 CFStringRef subject = SecCertificateCopySubjectString(cert);
198 if (subject) {
199 print_line(subject);
200 CFRelease(subject);
201 } else {
202 print_line(CFSTR("no subject"));
203 }
204
205 print_plist(plist);
206 CFRelease(plist);
207 #else
208 CFStringRef certName = NULL;
209 OSStatus status = SecCertificateInferLabel(cert, &certName);
210 if (certName) {
211 print_line(certName);
212 CFRelease(certName);
213 }
214 else {
215 fprintf(stdout, "ERROR: unable to read certificate name\n");
216 }
217 #endif
218 }