2 * Copyright (c) 2003-2008,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * printCert.c - utility functions for printing certificate info
28 #include "printCert.h"
29 #include <CoreFoundation/CoreFoundation.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecTrustPriv.h>
33 void fprint_string(CFStringRef string
, FILE *file
) {
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
;
46 void print_line(CFStringRef line
) {
47 fprint_string(line
, stdout
);
51 static void printPlist(CFArrayRef plist
, CFIndex indent
, CFIndex maxWidth
) {
52 CFIndex count
= CFArrayGetCount(plist
);
54 for (ix
= 0; ix
< count
; ++ix
) {
55 CFDictionaryRef prop
= (CFDictionaryRef
)CFArrayGetValueAtIndex(plist
,
57 CFStringRef pType
= (CFStringRef
)CFDictionaryGetValue(prop
,
59 CFStringRef label
= (CFStringRef
)CFDictionaryGetValue(prop
,
60 kSecPropertyKeyLabel
);
61 CFStringRef llabel
= (CFStringRef
)CFDictionaryGetValue(prop
,
62 kSecPropertyKeyLocalizedLabel
);
63 CFTypeRef value
= (CFTypeRef
)CFDictionaryGetValue(prop
,
64 kSecPropertyKeyValue
);
66 bool isSection
= CFEqual(pType
, kSecPropertyTypeSection
);
67 CFMutableStringRef line
= CFStringCreateMutable(NULL
, 0);
69 for (jx
= 0; jx
< indent
; ++jx
) {
70 CFStringAppend(line
, CFSTR(" "));
73 CFStringAppend(line
, llabel
);
75 for (jx
= CFStringGetLength(llabel
) + indent
* 4;
76 jx
< maxWidth
; ++jx
) {
77 CFStringAppend(line
, CFSTR(" "));
79 CFStringAppend(line
, CFSTR(" : "));
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
);
100 CFStringAppendFormat(line
, NULL
, CFSTR("[%d bytes] "), length
);
101 const UInt8
*bytes
= CFDataGetBytePtr(data
);
102 for (jx
= 0; jx
< length
; ++jx
) {
104 CFStringAppendFormat(line
, NULL
, CFSTR("%02X"), bytes
[jx
]);
105 else if (jx
< 15 || length
<= 20)
106 CFStringAppendFormat(line
, NULL
, CFSTR(" %02X"),
109 CFStringAppend(line
, CFSTR(" ..."));
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
);
121 CFTimeZoneRef tz
= CFTimeZoneCreateWithTimeIntervalFromGMT(NULL
, 0.0);
122 CFDateFormatterSetProperty(df
, kCFDateFormatterTimeZone
, tz
);
124 ds
= CFDateFormatterCreateStringWithDate(NULL
, df
, date
);
127 ds
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%g"), CFDateGetAbsoluteTime(date
));
129 CFStringAppend(line
, ds
);
132 } else if (CFEqual(pType
, kSecPropertyTypeURL
)) {
133 CFURLRef url
= (CFURLRef
)value
;
134 CFStringAppend(line
, CFSTR("<"));
135 CFStringAppend(line
, CFURLGetString(url
));
136 CFStringAppend(line
, CFSTR(">"));
138 CFStringAppendFormat(line
, NULL
, CFSTR("*unknown type %@* = %@"),
142 if (!isSection
|| label
)
146 printPlist((CFArrayRef
)value
, indent
+ 1, maxWidth
);
151 static CFIndex
maxLabelWidth(CFArrayRef plist
, CFIndex indent
) {
152 CFIndex count
= CFArrayGetCount(plist
);
154 CFIndex maxWidth
= 0;
155 for (ix
= 0; ix
< count
; ++ix
) {
156 CFDictionaryRef prop
= (CFDictionaryRef
)CFArrayGetValueAtIndex(plist
,
158 CFStringRef pType
= (CFStringRef
)CFDictionaryGetValue(prop
,
159 kSecPropertyKeyType
);
160 CFStringRef llabel
= (CFStringRef
)CFDictionaryGetValue(prop
,
161 kSecPropertyKeyLocalizedLabel
);
162 CFTypeRef value
= (CFTypeRef
)CFDictionaryGetValue(prop
,
163 kSecPropertyKeyValue
);
165 if (CFEqual(pType
, kSecPropertyTypeSection
)) {
166 CFIndex width
= maxLabelWidth((CFArrayRef
)value
, indent
+ 1);
167 if (width
> maxWidth
)
170 CFIndex width
= indent
* 4 + CFStringGetLength(llabel
);
171 if (width
> maxWidth
)
179 void print_plist(CFArrayRef plist
) {
181 printPlist(plist
, 0, maxLabelWidth(plist
, 0));
183 printf("NULL plist\n");
186 void print_cert(SecCertificateRef cert
, bool verbose
) {
187 // TODO: merge these when all SecCertificate APIs are present on both iOS and OS X
191 plist
= SecCertificateCopyProperties(cert
);
193 CFAbsoluteTime now
= CFAbsoluteTimeGetCurrent();
194 plist
= SecCertificateCopySummaryProperties(cert
, now
);
197 CFStringRef subject
= SecCertificateCopySubjectString(cert
);
202 print_line(CFSTR("no subject"));
208 CFStringRef certName
= NULL
;
209 OSStatus status
= SecCertificateInferLabel(cert
, &certName
);
211 print_line(certName
);
215 fprintf(stdout
, "ERROR: unable to read certificate name\n");