2 * Copyright (c) 2003-2008,2011,2013-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@
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>
36 static void printPlist(CFArrayRef plist
, CFIndex indent
, CFIndex maxWidth
) {
37 CFIndex count
= CFArrayGetCount(plist
);
39 for (ix
= 0; ix
< count
; ++ix
) {
40 CFDictionaryRef prop
= (CFDictionaryRef
)CFArrayGetValueAtIndex(plist
,
42 CFStringRef pType
= (CFStringRef
)CFDictionaryGetValue(prop
,
44 CFStringRef label
= (CFStringRef
)CFDictionaryGetValue(prop
,
45 kSecPropertyKeyLabel
);
46 CFStringRef llabel
= (CFStringRef
)CFDictionaryGetValue(prop
,
47 kSecPropertyKeyLocalizedLabel
);
48 CFTypeRef value
= (CFTypeRef
)CFDictionaryGetValue(prop
,
49 kSecPropertyKeyValue
);
51 bool isSection
= CFEqual(pType
, kSecPropertyTypeSection
);
52 CFMutableStringRef line
= CFStringCreateMutable(NULL
, 0);
54 for (jx
= 0; jx
< indent
; ++jx
) {
55 CFStringAppend(line
, CFSTR(" "));
58 CFStringAppend(line
, llabel
);
60 for (jx
= CFStringGetLength(llabel
) + indent
* 4;
61 jx
< maxWidth
; ++jx
) {
62 CFStringAppend(line
, CFSTR(" "));
64 CFStringAppend(line
, CFSTR(" : "));
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
);
85 CFStringAppendFormat(line
, NULL
, CFSTR("[%" PRIdCFIndex
" bytes] "), length
);
86 const UInt8
*bytes
= CFDataGetBytePtr(data
);
87 for (jx
= 0; jx
< length
; ++jx
) {
89 CFStringAppendFormat(line
, NULL
, CFSTR("%02X"), bytes
[jx
]);
90 else if (jx
< 15 || length
<= 20)
91 CFStringAppendFormat(line
, NULL
, CFSTR(" %02X"),
94 CFStringAppend(line
, CFSTR(" ..."));
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
);
106 CFTimeZoneRef tz
= CFTimeZoneCreateWithTimeIntervalFromGMT(NULL
, 0.0);
107 CFDateFormatterSetProperty(df
, kCFDateFormatterTimeZone
, tz
);
109 ds
= CFDateFormatterCreateStringWithDate(NULL
, df
, date
);
112 ds
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%g"), CFDateGetAbsoluteTime(date
));
114 CFStringAppend(line
, ds
);
117 } else if (CFEqual(pType
, kSecPropertyTypeURL
)) {
118 CFURLRef url
= (CFURLRef
)value
;
119 CFStringAppend(line
, CFSTR("<"));
120 CFStringAppend(line
, CFURLGetString(url
));
121 CFStringAppend(line
, CFSTR(">"));
123 CFStringAppendFormat(line
, NULL
, CFSTR("*unknown type %@* = %@"),
127 if (!isSection
|| label
)
128 CFStringWriteToFileWithNewline(line
, stdout
);
131 printPlist((CFArrayRef
)value
, indent
+ 1, maxWidth
);
136 static CFIndex
maxLabelWidth(CFArrayRef plist
, CFIndex indent
) {
137 CFIndex count
= CFArrayGetCount(plist
);
139 CFIndex maxWidth
= 0;
140 for (ix
= 0; ix
< count
; ++ix
) {
141 CFDictionaryRef prop
= (CFDictionaryRef
)CFArrayGetValueAtIndex(plist
,
143 CFStringRef pType
= (CFStringRef
)CFDictionaryGetValue(prop
,
144 kSecPropertyKeyType
);
145 CFStringRef llabel
= (CFStringRef
)CFDictionaryGetValue(prop
,
146 kSecPropertyKeyLocalizedLabel
);
147 CFTypeRef value
= (CFTypeRef
)CFDictionaryGetValue(prop
,
148 kSecPropertyKeyValue
);
150 if (CFEqual(pType
, kSecPropertyTypeSection
)) {
151 CFIndex width
= maxLabelWidth((CFArrayRef
)value
, indent
+ 1);
152 if (width
> maxWidth
)
155 CFIndex width
= indent
* 4 + CFStringGetLength(llabel
);
156 if (width
> maxWidth
)
164 void print_plist(CFArrayRef plist
) {
166 printPlist(plist
, 0, maxLabelWidth(plist
, 0));
168 printf("NULL plist\n");
171 void print_cert(SecCertificateRef cert
, bool verbose
) {
175 plist
= SecCertificateCopyProperties(cert
);
177 CFAbsoluteTime now
= CFAbsoluteTimeGetCurrent();
178 plist
= SecCertificateCopySummaryProperties(cert
, now
);
181 CFStringRef subject
= SecCertificateCopySubjectString(cert
);
183 CFStringWriteToFileWithNewline(subject
, stdout
);
186 CFStringWriteToFileWithNewline(CFSTR("no subject"), stdout
);
190 CFReleaseSafe(plist
);