]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Tool/show_certificates.c
Security-58286.70.7.tar.gz
[apple/security.git] / OSX / sec / Security / Tool / show_certificates.c
1 /*
2 * Copyright (c) 2003-2007,2009-2010,2013-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 * keychain_find.c
24 */
25
26 #include <TargetConditionals.h>
27 #if TARGET_OS_EMBEDDED
28
29 #include "SecurityCommands.h"
30
31 #include "security.h"
32 #include "SecurityTool/print_cert.h"
33 #include "SecBase64.h"
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41
42 #include <SecurityTool/tool_errors.h>
43
44 #include <Security/SecItem.h>
45
46 #include <CoreFoundation/CFArray.h>
47 #include <CoreFoundation/CFDate.h>
48 #include <CoreFoundation/CFNumber.h>
49 #include <CoreFoundation/CFString.h>
50
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>
57
58 #include <SecurityTool/readline.h>
59
60 #include <utilities/SecCFWrappers.h>
61 #include "keychain_util.h"
62
63 typedef uint32_t SecProtocolType;
64 typedef uint32_t SecAuthenticationType;
65
66
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[] = {
73 "invalid",
74 "proceed",
75 "confirm",
76 "deny",
77 "unspecified",
78 "recoverable trust failure",
79 "fatal trust failure",
80 "other error",
81 };
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);
93 if (verbose) {
94 printf("* cert %ld detail properties *\n", ix);
95 properties = SecTrustCopyDetailedPropertiesAtIndex(trust, ix);
96 print_plist(properties);
97 CFReleaseNull(properties);
98 }
99 }
100
101 CFDictionaryRef info = SecTrustCopyInfo(trust);
102 if (info) {
103 printf("* info *\n");
104 CFShow(info);
105 CFReleaseNull(info);
106 }
107 CFReleaseNull(policy);
108 }
109
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);
116 char *p = buffer;
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);
121 if (result) {
122 free(buffer);
123 return result;
124 }
125 p += sprintf(p, "\n-----END %s-----\n", pem_name);
126 size_t res = fwrite(buffer, 1, p - buffer, stream);
127 fflush(stream);
128 bzero(buffer, p - buffer);
129 free(buffer);
130 return res;
131 }
132
133 int keychain_show_certificates(int argc, char * const *argv)
134 {
135 int ch, result = 0;
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);
144
145 while ((ch = getopt(argc, argv, "kfq:pstv")) != -1)
146 {
147 switch (ch)
148 {
149 case 'k':
150 keychain_certs = true;
151 break;
152 case 'p':
153 output_pem = true;
154 break;
155 case 's':
156 output_subject = true;
157 break;
158 case 'v':
159 verbose = true;
160 break;
161 case 't':
162 trust_eval = true;
163 break;
164 case 'f':
165 output_finger_print = true;
166 break;
167 case 'q':
168 if (!keychain_query_parse_cstring(query, optarg)) {
169 CFReleaseNull(query);
170 return 1;
171 }
172 keychain_certs = true;
173 break;
174 case '?':
175 default:
176 return SHOW_USAGE_MESSAGE;
177 }
178 }
179
180 argc -= optind;
181 argv += optind;
182
183 if ((keychain_certs && argc > 0) || (!keychain_certs && argc < 1))
184 result = 2;
185
186 if (trust_eval)
187 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
188
189 CFArrayRef kc_certs = NULL;
190 int arg;
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);
196 return 1;
197 }
198 }
199 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
200 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
201 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
202 CFTypeRef results;
203 if (!SecItemCopyMatching(query, &results)) {
204 kc_certs = results;
205 argc = (int) CFArrayGetCount(kc_certs);
206 }
207 }
208
209 for (arg = 0; arg < argc; ++arg) {
210 SecCertificateRef cert = NULL;
211 if (keychain_certs) {
212 cert = (SecCertificateRef)CFArrayGetValueAtIndex(kc_certs, arg);
213 } else {
214 CFDataRef data = copyFileContents(argv[arg]);
215 if (data) {
216 cert = SecCertificateCreateWithData(
217 kCFAllocatorDefault, data);
218 if (!cert) {
219 /* DER failed, try PEM. */
220 cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data);
221 }
222 CFRelease(data);
223 } else {
224 result = 1;
225 }
226 }
227
228 if (cert) {
229 if (!keychain_certs) {
230 printf(
231 "*******************************************************\n"
232 "%s\n"
233 "*******************************************************\n"
234 , argv[arg]);
235 }
236 if (trust_eval) {
237 if (keychain_certs) {
238 CFArraySetValueAtIndex(certs, 0, cert);
239 show_cert_eval(certs, verbose);
240 } else {
241 CFArrayAppendValue(certs, cert);
242 }
243 } else {
244 if (verbose) {
245 print_cert(cert, verbose);
246 } else if (output_subject) {
247 CFStringRef subject = SecCertificateCopySubjectString(cert);
248 if (subject) {
249 CFStringWriteToFileWithNewline(subject, stdout);
250 CFRelease(subject);
251 }
252 } else if (!output_pem) {
253 print_cert(cert, verbose);
254 }
255 }
256 if (output_finger_print) {
257 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert);
258 if (key_fingerprint) {
259 int i;
260 CFIndex j = CFDataGetLength(key_fingerprint);
261 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint);
262
263 fprintf(stdout, "Key fingerprint:");
264 for (i = 0; i < j; i++) {
265 fprintf(stdout, " %02X", byte[i]);
266 }
267 fprintf(stdout, "\n");
268 }
269 CFReleaseSafe(key_fingerprint);
270 }
271 if (output_pem) {
272 print_buffer_pem(stdout, "CERTIFICATE",
273 SecCertificateGetLength(cert),
274 SecCertificateGetBytePtr(cert));
275 }
276 if (!keychain_certs) {
277 CFRelease(cert);
278 }
279 } else {
280 result = 1;
281 fprintf(stderr, "file %s: does not contain a valid certificate",
282 argv[arg]);
283 }
284 }
285
286 if (trust_eval && !keychain_certs)
287 show_cert_eval(certs, verbose);
288
289 CFReleaseSafe(kc_certs);
290 CFReleaseSafe(certs);
291
292 return result;
293 }
294
295 static bool isSettingWithResult(CFDictionaryRef setting, SecTrustSettingsResult result) {
296 CFNumberRef value = CFDictionaryGetValue(setting, kSecTrustSettingsResult);
297 if (!isNumberOfType(value, kCFNumberSInt64Type)) {
298 return false;
299 }
300 int64_t setting_result = 0;
301 if (!CFNumberGetValue(value, kCFNumberSInt64Type, &setting_result) ||
302 (setting_result != result)) {
303 return false;
304 }
305 return true;
306 }
307
308 static bool isUnconstrainedSettingWithResult(CFDictionaryRef setting, SecTrustSettingsResult result) {
309 if (!isDictionary(setting) || (CFDictionaryGetCount(setting) != 1)) {
310 return false;
311 }
312
313 return isSettingWithResult(setting, result);
314 }
315
316 static bool isDenyTrustSetting(CFArrayRef trust_settings) {
317 if (CFArrayGetCount(trust_settings) != 1) {
318 return false;
319 }
320
321 return isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings, 0),
322 kSecTrustSettingsResultDeny);
323 }
324
325 static bool isPartialSSLTrustSetting(CFArrayRef trust_settings) {
326 if (CFArrayGetCount(trust_settings) != 2) {
327 return false;
328 }
329
330 /* Second setting is a blanket "Trust" */
331 if (!isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings, 1),
332 kSecTrustSettingsResultTrustRoot) &&
333 !isUnconstrainedSettingWithResult(CFArrayGetValueAtIndex(trust_settings, 1),
334 kSecTrustSettingsResultTrustAsRoot)) {
335 return false;
336 }
337
338 /* First setting is "upspecified" for SSL policy */
339 CFDictionaryRef setting = CFArrayGetValueAtIndex(trust_settings, 0);
340 if (!isDictionary(setting) || (CFDictionaryGetCount(setting) < 2)) {
341 return false;
342 }
343 if (!isSettingWithResult(setting, kSecTrustSettingsResultUnspecified)) {
344 return false;
345 }
346 if (!CFEqualSafe(CFDictionaryGetValue(setting, kSecTrustSettingsPolicy), kSecPolicyAppleSSL)) {
347 return false;
348 }
349
350 return true;
351 }
352
353 int trust_store_show_certificates(int argc, char * const *argv)
354 {
355 int ch, result = 0;
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;
363
364 while ((ch = getopt(argc, argv, "fpstvk")) != -1)
365 {
366 switch (ch)
367 {
368 case 'p':
369 output_pem = true;
370 break;
371 case 's':
372 output_subject = true;
373 break;
374 case 'v':
375 verbose = true;
376 break;
377 case 't':
378 trust_settings = true;
379 break;
380 case 'f':
381 output_finger_print = true;
382 break;
383 case 'k':
384 output_keyid = true;
385 break;
386 case '?':
387 default:
388 return SHOW_USAGE_MESSAGE;
389 }
390 }
391
392 if(SecTrustStoreCopyAll(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
393 &certs) || !certs) {
394 fprintf(stderr, "failed to get trust store contents for user\n");
395 return 1;
396 }
397
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;
404
405 certSettingsPair = CFArrayGetValueAtIndex(certs, ix);
406 certData = (CFDataRef)CFArrayGetValueAtIndex(certSettingsPair, 0);
407 cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
408 if (!cert) {
409 fprintf(stderr, "failed to get cert at %ld\n",ix);
410 return 1;
411 }
412 if (verbose) {
413 print_cert(cert, verbose);
414 } else if (output_subject) {
415 CFStringRef subject = SecCertificateCopySubjectString(cert);
416 if (subject) {
417 CFStringWriteToFileWithNewline(subject, stdout);
418 CFRelease(subject);
419 }
420 } else if (output_pem) {
421 print_buffer_pem(stdout, "CERTIFICATE",
422 SecCertificateGetLength(cert),
423 SecCertificateGetBytePtr(cert));
424 } else {
425 print_cert(cert, verbose);
426 }
427 if (output_keyid) {
428 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert);
429 if (key_fingerprint) {
430 int i;
431 CFIndex j = CFDataGetLength(key_fingerprint);
432 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint);
433
434 fprintf(stdout, "Keyid:");
435 for (i = 0; i < j; i++) {
436 fprintf(stdout, " %02X", byte[i]);
437 }
438 fprintf(stdout, "\n");
439 }
440 CFReleaseSafe(key_fingerprint);
441 }
442 if (output_finger_print) {
443 CFDataRef fingerprint = SecCertificateGetSHA1Digest(cert);
444 if (fingerprint) {
445 int i;
446 CFIndex j = CFDataGetLength(fingerprint);
447 const uint8_t *byte = CFDataGetBytePtr(fingerprint);
448
449 fprintf(stdout, "Fingerprint:");
450 for (i = 0; i < j; i++) {
451 fprintf(stdout, " %02X", byte[i]);
452 }
453 fprintf(stdout, "\n");
454 }
455 }
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);
461 CFReleaseNull(cert);
462 return 1;
463 }
464
465 /* These are some trust settings configs used by ManagedConfiguration on iOS */
466 if (CFArrayGetCount(trust_settings) == 0) {
467 /* Full trust */
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");
473 } else {
474 CFStringRef settings = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), trust_settings);
475 if (settings) {
476 char *settingsStr = CFStringToCString(settings);
477 if (settingsStr) {
478 fprintf(stdout, "Unknown trust settings:\n%s\n", settingsStr);
479 free(settingsStr);
480 }
481 CFRelease(settings);
482 }
483 }
484
485
486 }
487 printf("*******************************************************\n");
488 CFReleaseNull(cert);
489 }
490
491 CFRelease(certs);
492 return result;
493 }
494
495 #endif // TARGET_OS_EMBEDDED