2 * Copyright (c) 2003-2007,2009-2010,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@
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>
55 #include <Security/SecTrustStore.h>
56 #include <Security/SecTrustSettings.h>
58 #include <SecurityTool/readline.h>
60 #include <utilities/SecCFWrappers.h>
61 #include "keychain_util.h"
63 typedef uint32_t SecProtocolType
;
64 typedef uint32_t SecAuthenticationType
;
67 static void show_cert_eval(CFArrayRef certs
, bool verbose
) {
68 SecPolicyRef policy
= SecPolicyCreateSSL(true, NULL
);
69 SecTrustRef trust
= NULL
;
70 SecTrustCreateWithCertificates(certs
, policy
, &trust
);
71 SecTrustResultType trustResult
;
72 const char *trustResults
[] = {
78 "recoverable trust failure",
79 "fatal trust failure",
82 (void) SecTrustEvaluate(trust
, &trustResult
);
83 printf("* trust: %s *\n", trustResults
[trustResult
]);
84 CFArrayRef properties
= SecTrustCopyProperties(trust
);
85 print_plist(properties
);
86 CFReleaseNull(properties
);
87 CFIndex ix
, count
= SecTrustGetCertificateCount(trust
);
88 for (ix
= 0; ix
< count
; ++ix
) {
89 printf("* cert %ld summary properties *\n", ix
);
90 properties
= SecTrustCopySummaryPropertiesAtIndex(trust
, ix
);
91 print_plist(properties
);
92 CFReleaseNull(properties
);
94 printf("* cert %ld detail properties *\n", ix
);
95 properties
= SecTrustCopyDetailedPropertiesAtIndex(trust
, ix
);
96 print_plist(properties
);
97 CFReleaseNull(properties
);
101 CFDictionaryRef info
= SecTrustCopyInfo(trust
);
103 printf("* info *\n");
107 CFReleaseNull(policy
);
110 static size_t print_buffer_pem(FILE *stream
, const char *pem_name
, size_t length
,
111 const uint8_t *bytes
) {
112 size_t pem_name_len
= strlen(pem_name
);
113 size_t b64_len
= SecBase64Encode2(NULL
, length
, NULL
, 0,
114 kSecB64_F_LINE_LEN_USE_PARAM
, 64, NULL
);
115 char *buffer
= malloc(33 + 2 * pem_name_len
+ b64_len
);
117 p
+= sprintf(buffer
, "-----BEGIN %s-----\n", pem_name
);
118 SecBase64Result result
;
119 p
+= SecBase64Encode2(bytes
, length
, p
, b64_len
,\
120 kSecB64_F_LINE_LEN_USE_PARAM
, 64, &result
);
125 p
+= sprintf(p
, "\n-----END %s-----\n", pem_name
);
126 size_t res
= fwrite(buffer
, 1, p
- buffer
, stream
);
128 bzero(buffer
, p
- buffer
);
133 int keychain_show_certificates(int argc
, char * const *argv
)
136 bool output_subject
= false;
137 bool verbose
= false;
138 bool trust_eval
= false;
139 bool keychain_certs
= false;
140 bool output_pem
= false;
141 bool output_finger_print
= false;
142 CFMutableArrayRef certs
= NULL
;
143 CFMutableDictionaryRef query
= CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
145 while ((ch
= getopt(argc
, argv
, "kfq:pstv")) != -1)
150 keychain_certs
= true;
156 output_subject
= true;
165 output_finger_print
= true;
168 if (!keychain_query_parse_cstring(query
, optarg
)) {
169 CFReleaseNull(query
);
172 keychain_certs
= true;
176 return SHOW_USAGE_MESSAGE
;
183 if ((keychain_certs
&& argc
> 0) || (!keychain_certs
&& argc
< 1))
187 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
189 CFArrayRef kc_certs
= NULL
;
191 if (keychain_certs
) {
192 for (arg
= 0; arg
< argc
; ++arg
) {
193 if (!keychain_query_parse_cstring(query
, argv
[arg
])) {
194 CFReleaseSafe(query
);
195 CFReleaseSafe(certs
);
199 CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
);
200 CFDictionarySetValue(query
, kSecMatchLimit
, kSecMatchLimitAll
);
201 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
203 if (!SecItemCopyMatching(query
, &results
)) {
205 argc
= (int) CFArrayGetCount(kc_certs
);
209 for (arg
= 0; arg
< argc
; ++arg
) {
210 SecCertificateRef cert
= NULL
;
211 if (keychain_certs
) {
212 cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(kc_certs
, arg
);
214 CFDataRef data
= copyFileContents(argv
[arg
]);
216 cert
= SecCertificateCreateWithData(
217 kCFAllocatorDefault
, data
);
219 /* DER failed, try PEM. */
220 cert
= SecCertificateCreateWithPEM(kCFAllocatorDefault
, data
);
229 if (!keychain_certs
) {
231 "*******************************************************\n"
233 "*******************************************************\n"
237 if (keychain_certs
) {
238 CFArraySetValueAtIndex(certs
, 0, cert
);
239 show_cert_eval(certs
, verbose
);
241 CFArrayAppendValue(certs
, cert
);
245 print_cert(cert
, verbose
);
246 } else if (output_subject
) {
247 CFStringRef subject
= SecCertificateCopySubjectString(cert
);
249 CFStringWriteToFileWithNewline(subject
, stdout
);
252 } else if (!output_pem
) {
253 print_cert(cert
, verbose
);
256 if (output_finger_print
) {
257 CFDataRef key_fingerprint
= SecCertificateCopyPublicKeySHA1Digest(cert
);
258 if (key_fingerprint
) {
260 CFIndex j
= CFDataGetLength(key_fingerprint
);
261 const uint8_t *byte
= CFDataGetBytePtr(key_fingerprint
);
263 fprintf(stdout
, "Key fingerprint:");
264 for (i
= 0; i
< j
; i
++) {
265 fprintf(stdout
, " %02X", byte
[i
]);
267 fprintf(stdout
, "\n");
269 CFReleaseSafe(key_fingerprint
);
272 print_buffer_pem(stdout
, "CERTIFICATE",
273 SecCertificateGetLength(cert
),
274 SecCertificateGetBytePtr(cert
));
276 if (!keychain_certs
) {
281 fprintf(stderr
, "file %s: does not contain a valid certificate",
286 if (trust_eval
&& !keychain_certs
)
287 show_cert_eval(certs
, verbose
);
289 CFReleaseSafe(kc_certs
);
290 CFReleaseSafe(certs
);
295 static bool isSettingWithResult(CFDictionaryRef setting
, SecTrustSettingsResult result
) {
296 CFNumberRef value
= CFDictionaryGetValue(setting
, kSecTrustSettingsResult
);
297 if (!isNumberOfType(value
, kCFNumberSInt64Type
)) {
300 int64_t setting_result
= 0;
301 if (!CFNumberGetValue(value
, kCFNumberSInt64Type
, &setting_result
) ||
302 (setting_result
!= result
)) {
308 static bool isUnconstrainedSettingWithResult(CFDictionaryRef setting
, SecTrustSettingsResult result
) {
309 if (!isDictionary(setting
) || (CFDictionaryGetCount(setting
) != 1)) {
313 return isSettingWithResult(setting
, result
);
316 static bool isDenyTrustSetting(CFArrayRef trust_settings
) {
317 if (CFArrayGetCount(trust_settings
) != 1) {
321 return isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings
, 0),
322 kSecTrustSettingsResultDeny
);
325 static bool isPartialSSLTrustSetting(CFArrayRef trust_settings
) {
326 if (CFArrayGetCount(trust_settings
) != 2) {
330 /* Second setting is a blanket "Trust" */
331 if (!isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings
, 1),
332 kSecTrustSettingsResultTrustRoot
) &&
333 !isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings
, 1),
334 kSecTrustSettingsResultTrustAsRoot
)) {
338 /* First setting is "upspecified" for SSL policy */
339 CFDictionaryRef setting
= CFArrayGetValueAtIndex(trust_settings
, 0);
340 if (!isDictionary(setting
) || (CFDictionaryGetCount(setting
) < 2)) {
343 if (!isSettingWithResult(setting
, kSecTrustSettingsResultUnspecified
)) {
346 if (!CFEqualSafe(CFDictionaryGetValue(setting
, kSecTrustSettingsPolicy
), kSecPolicyAppleSSL
)) {
353 int trust_store_show_certificates(int argc
, char * const *argv
)
356 bool output_subject
= false;
357 bool verbose
= false;
358 bool trust_settings
= false;
359 bool output_pem
= false;
360 bool output_finger_print
= false;
361 bool output_keyid
= false;
362 CFArrayRef certs
= NULL
;
364 while ((ch
= getopt(argc
, argv
, "fpstvk")) != -1)
372 output_subject
= true;
378 trust_settings
= true;
381 output_finger_print
= true;
388 return SHOW_USAGE_MESSAGE
;
392 if(SecTrustStoreCopyAll(SecTrustStoreForDomain(kSecTrustStoreDomainUser
),
394 fprintf(stderr
, "failed to get trust store contents for user\n");
398 CFIndex ix
, count
= CFArrayGetCount(certs
);
399 if (count
) printf("*******************************************************\n");
400 for (ix
= 0; ix
< count
; ix
++) {
401 CFArrayRef certSettingsPair
= NULL
;
402 CFDataRef certData
= NULL
;
403 SecCertificateRef cert
= NULL
;
405 certSettingsPair
= CFArrayGetValueAtIndex(certs
, ix
);
406 certData
= (CFDataRef
)CFArrayGetValueAtIndex(certSettingsPair
, 0);
407 cert
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
409 fprintf(stderr
, "failed to get cert at %ld\n",ix
);
413 print_cert(cert
, verbose
);
414 } else if (output_subject
) {
415 CFStringRef subject
= SecCertificateCopySubjectString(cert
);
417 CFStringWriteToFileWithNewline(subject
, stdout
);
420 } else if (output_pem
) {
421 print_buffer_pem(stdout
, "CERTIFICATE",
422 SecCertificateGetLength(cert
),
423 SecCertificateGetBytePtr(cert
));
425 print_cert(cert
, verbose
);
428 CFDataRef key_fingerprint
= SecCertificateCopyPublicKeySHA1Digest(cert
);
429 if (key_fingerprint
) {
431 CFIndex j
= CFDataGetLength(key_fingerprint
);
432 const uint8_t *byte
= CFDataGetBytePtr(key_fingerprint
);
434 fprintf(stdout
, "Keyid:");
435 for (i
= 0; i
< j
; i
++) {
436 fprintf(stdout
, " %02X", byte
[i
]);
438 fprintf(stdout
, "\n");
440 CFReleaseSafe(key_fingerprint
);
442 if (output_finger_print
) {
443 CFDataRef fingerprint
= SecCertificateGetSHA1Digest(cert
);
446 CFIndex j
= CFDataGetLength(fingerprint
);
447 const uint8_t *byte
= CFDataGetBytePtr(fingerprint
);
449 fprintf(stdout
, "Fingerprint:");
450 for (i
= 0; i
< j
; i
++) {
451 fprintf(stdout
, " %02X", byte
[i
]);
453 fprintf(stdout
, "\n");
456 if (trust_settings
) {
457 CFPropertyListRef trust_settings
= NULL
;
458 trust_settings
= CFArrayGetValueAtIndex(certSettingsPair
, 1);
459 if (trust_settings
&& CFGetTypeID(trust_settings
) != CFArrayGetTypeID()) {
460 fprintf(stderr
, "failed to get trust settings for cert %ld\n", ix
);
465 /* These are some trust settings configs used by ManagedConfiguration on iOS */
466 if (CFArrayGetCount(trust_settings
) == 0) {
468 fprintf(stdout
, "Full trust enabled\n");
469 } else if (isDenyTrustSetting(trust_settings
)) {
470 fprintf(stdout
, "Administrator blacklisted\n");
471 } else if (isPartialSSLTrustSetting(trust_settings
)) {
472 fprintf(stdout
, "Partial trust enabled\n");
474 CFStringRef settings
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@"), trust_settings
);
476 char *settingsStr
= CFStringToCString(settings
);
478 fprintf(stdout
, "Unknown trust settings:\n%s\n", settingsStr
);
487 printf("*******************************************************\n");
495 #endif // TARGET_OS_EMBEDDED