2 * Copyright (c) 2003-2007,2009-2010 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@
26 #include <TargetConditionals.h>
27 #if TARGET_OS_EMBEDDED
29 #include "SecurityCommands.h"
32 #include "SecurityTool/print_cert.h"
33 #include "SecBase64.h"
39 #include <sys/types.h>
42 #include <SecurityTool/tool_errors.h>
44 #include <Security/SecItem.h>
46 #include <CoreFoundation/CFArray.h>
47 #include <CoreFoundation/CFDate.h>
48 #include <CoreFoundation/CFNumber.h>
49 #include <CoreFoundation/CFString.h>
51 #include <Security/SecCertificatePriv.h>
52 #include <Security/SecPolicyPriv.h>
53 #include <Security/SecTrustPriv.h>
54 #include <Security/SecInternal.h>
56 #include <SecurityTool/readline.h>
58 #include <utilities/SecCFWrappers.h>
60 typedef uint32_t SecProtocolType
;
61 typedef uint32_t SecAuthenticationType
;
64 keychain_query_parse_string(CFMutableDictionaryRef q
, CFStringRef s
) {
67 CFStringRef key
= NULL
;
68 CFMutableStringRef str
= CFStringCreateMutable(0, 0);
69 CFRange rng
= { .location
= 0, .length
= CFStringGetLength(s
) };
70 CFCharacterSetRef cs_key
= CFCharacterSetCreateWithCharactersInString(0, CFSTR("=\\"));
71 CFCharacterSetRef cs_value
= CFCharacterSetCreateWithCharactersInString(0, CFSTR(",\\"));
75 bool complete
= false;
77 r
.location
= rng
.location
;
79 sub
= CFStringCreateWithSubstring(0, s
, r
);
81 } else if (CFStringFindCharacterFromSet(s
, inkey
? cs_key
: cs_value
, rng
, 0, &r
)) {
82 if (CFStringGetCharacterAtIndex(s
, r
.location
) == '\\') {
87 CFIndex next
= r
.location
+ 1;
88 r
.length
= r
.location
- rng
.location
;
89 r
.location
= rng
.location
;
90 sub
= CFStringCreateWithSubstring(0, s
, r
);
91 rng
.length
-= next
- rng
.location
;
94 sub
= CFStringCreateWithSubstring(0, s
, rng
);
95 rng
.location
+= rng
.length
;
99 CFStringAppend(str
, sub
);
102 CFStringRef value
= CFStringCreateCopy(0, str
);
103 CFStringReplaceAll(str
, CFSTR(""));
107 CFDictionarySetValue(q
, key
, value
);
108 CFReleaseNull(value
);
115 /* Dangeling key value is true?. */
116 CFDictionarySetValue(q
, key
, kCFBooleanTrue
);
123 keychain_query_parse_cstring(CFMutableDictionaryRef q
, const char *query
) {
125 s
= CFStringCreateWithCStringNoCopy(0, query
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
126 keychain_query_parse_string(q
, s
);
130 static void show_cert_eval(CFArrayRef certs
, bool verbose
) {
131 SecPolicyRef policy
= SecPolicyCreateSSL(true, NULL
);
132 SecTrustRef trust
= NULL
;
133 OSStatus status
= SecTrustCreateWithCertificates(certs
, policy
, &trust
);
134 SecTrustResultType trustResult
;
135 const char *trustResults
[] = {
141 "recoverable trust failure",
142 "fatal trust failure",
145 status
= SecTrustEvaluate(trust
, &trustResult
);
146 printf("* trust: %s *\n", trustResults
[trustResult
]);
147 CFArrayRef properties
= SecTrustCopyProperties(trust
);
148 print_plist(properties
);
149 CFReleaseNull(properties
);
150 CFIndex ix
, count
= SecTrustGetCertificateCount(trust
);
151 for (ix
= 0; ix
< count
; ++ix
) {
152 printf("* cert %ld summary properties *\n", ix
);
153 properties
= SecTrustCopySummaryPropertiesAtIndex(trust
, ix
);
154 print_plist(properties
);
155 CFReleaseNull(properties
);
157 printf("* cert %ld detail properties *\n", ix
);
158 properties
= SecTrustCopyDetailedPropertiesAtIndex(trust
, ix
);
159 print_plist(properties
);
160 CFReleaseNull(properties
);
164 CFDictionaryRef info
= SecTrustCopyInfo(trust
);
166 printf("* info *\n");
172 static size_t print_buffer_pem(FILE *stream
, const char *pem_name
, size_t length
,
173 const uint8_t *bytes
) {
174 size_t pem_name_len
= strlen(pem_name
);
175 size_t b64_len
= SecBase64Encode2(NULL
, length
, NULL
, 0,
176 kSecB64_F_LINE_LEN_USE_PARAM
, 64, NULL
);
177 char *buffer
= malloc(33 + 2 * pem_name_len
+ b64_len
);
179 p
+= sprintf(buffer
, "-----BEGIN %s-----\n", pem_name
);
180 SecBase64Result result
;
181 p
+= SecBase64Encode2(bytes
, length
, p
, b64_len
,\
182 kSecB64_F_LINE_LEN_USE_PARAM
, 64, &result
);
187 p
+= sprintf(p
, "\n-----END %s-----\n", pem_name
);
188 size_t res
= fwrite(buffer
, 1, p
- buffer
, stream
);
190 bzero(buffer
, p
- buffer
);
195 int keychain_show_certificates(int argc
, char * const *argv
)
198 bool output_subject
= false;
199 bool verbose
= false;
200 bool trust_eval
= false;
201 bool keychain_certs
= false;
202 bool output_pem
= false;
203 bool output_finger_print
= false;
204 CFMutableArrayRef certs
= NULL
;
205 CFMutableDictionaryRef query
= CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
207 while ((ch
= getopt(argc
, argv
, "kfq:pstv")) != -1)
212 keychain_certs
= true;
218 output_subject
= true;
227 output_finger_print
= true;
230 keychain_query_parse_cstring(query
, optarg
);
231 keychain_certs
= true;
235 return 2; /* @@@ Return 2 triggers usage message. */
242 if ((keychain_certs
&& argc
> 0) || (!keychain_certs
&& argc
< 1))
246 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
248 CFArrayRef kc_certs
= NULL
;
250 if (keychain_certs
) {
251 for (arg
= 0; arg
< argc
; ++arg
) {
252 keychain_query_parse_cstring(query
, argv
[arg
]);
254 CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
);
255 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
256 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
258 if (!SecItemCopyMatching(query
, &results
)) {
260 argc
= (int) CFArrayGetCount(kc_certs
);
264 for (arg
= 0; arg
< argc
; ++arg
) {
265 SecCertificateRef cert
= NULL
;
266 if (keychain_certs
) {
267 cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(kc_certs
, arg
);
269 CFDataRef data
= copyFileContents(argv
[arg
]);
271 cert
= SecCertificateCreateWithData(
272 kCFAllocatorDefault
, data
);
274 /* DER failed, try PEM. */
275 cert
= SecCertificateCreateWithPEM(kCFAllocatorDefault
, data
);
284 if (!keychain_certs
) {
286 "*******************************************************\n"
288 "*******************************************************\n"
292 if (keychain_certs
) {
293 CFArraySetValueAtIndex(certs
, 0, cert
);
294 show_cert_eval(certs
, verbose
);
296 CFArrayAppendValue(certs
, cert
);
300 print_cert(cert
, verbose
);
301 } else if (output_subject
) {
302 CFStringRef subject
= SecCertificateCopySubjectString(cert
);
304 CFStringWriteToFileWithNewline(subject
, stdout
);
307 } else if (!output_pem
) {
308 print_cert(cert
, verbose
);
311 if (output_finger_print
) {
312 CFDataRef key_fingerprint
= SecCertificateCopyPublicKeySHA1Digest(cert
);
313 if (key_fingerprint
) {
315 CFIndex j
= CFDataGetLength(key_fingerprint
);
316 const uint8_t *byte
= CFDataGetBytePtr(key_fingerprint
);
318 fprintf(stdout
, "Key fingerprint:");
319 for (i
= 0; i
< j
; i
++) {
320 fprintf(stdout
, " %02X", byte
[i
]);
322 fprintf(stdout
, "\n");
326 print_buffer_pem(stdout
, "CERTIFICATE",
327 SecCertificateGetLength(cert
),
328 SecCertificateGetBytePtr(cert
));
330 if (!keychain_certs
) {
335 fprintf(stderr
, "file %s: does not contain a valid certificate",
340 if (trust_eval
&& !keychain_certs
)
341 show_cert_eval(certs
, verbose
);
343 CFReleaseSafe(kc_certs
);
344 CFReleaseSafe(certs
);
349 #endif // TARGET_OS_EMBEDDED