]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Tool/show_certificates.c
Security-57740.31.2.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
57 #include <SecurityTool/readline.h>
58
59 #include <utilities/SecCFWrappers.h>
60 #include "keychain_util.h"
61
62 typedef uint32_t SecProtocolType;
63 typedef uint32_t SecAuthenticationType;
64
65
66 static void show_cert_eval(CFArrayRef certs, bool verbose) {
67 SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
68 SecTrustRef trust = NULL;
69 SecTrustCreateWithCertificates(certs, policy, &trust);
70 SecTrustResultType trustResult;
71 const char *trustResults[] = {
72 "invalid",
73 "proceed",
74 "confirm",
75 "deny",
76 "unspecified",
77 "recoverable trust failure",
78 "fatal trust failure",
79 "other error",
80 };
81 (void) SecTrustEvaluate(trust, &trustResult);
82 printf("* trust: %s *\n", trustResults[trustResult]);
83 CFArrayRef properties = SecTrustCopyProperties(trust);
84 print_plist(properties);
85 CFReleaseNull(properties);
86 CFIndex ix, count = SecTrustGetCertificateCount(trust);
87 for (ix = 0; ix < count; ++ix) {
88 printf("* cert %ld summary properties *\n", ix);
89 properties = SecTrustCopySummaryPropertiesAtIndex(trust, ix);
90 print_plist(properties);
91 CFReleaseNull(properties);
92 if (verbose) {
93 printf("* cert %ld detail properties *\n", ix);
94 properties = SecTrustCopyDetailedPropertiesAtIndex(trust, ix);
95 print_plist(properties);
96 CFReleaseNull(properties);
97 }
98 }
99
100 CFDictionaryRef info = SecTrustCopyInfo(trust);
101 if (info) {
102 printf("* info *\n");
103 CFShow(info);
104 CFReleaseNull(info);
105 }
106 CFReleaseNull(policy);
107 }
108
109 static size_t print_buffer_pem(FILE *stream, const char *pem_name, size_t length,
110 const uint8_t *bytes) {
111 size_t pem_name_len = strlen(pem_name);
112 size_t b64_len = SecBase64Encode2(NULL, length, NULL, 0,
113 kSecB64_F_LINE_LEN_USE_PARAM, 64, NULL);
114 char *buffer = malloc(33 + 2 * pem_name_len + b64_len);
115 char *p = buffer;
116 p += sprintf(buffer, "-----BEGIN %s-----\n", pem_name);
117 SecBase64Result result;
118 p += SecBase64Encode2(bytes, length, p, b64_len,\
119 kSecB64_F_LINE_LEN_USE_PARAM, 64, &result);
120 if (result) {
121 free(buffer);
122 return result;
123 }
124 p += sprintf(p, "\n-----END %s-----\n", pem_name);
125 size_t res = fwrite(buffer, 1, p - buffer, stream);
126 fflush(stream);
127 bzero(buffer, p - buffer);
128 free(buffer);
129 return res;
130 }
131
132 int keychain_show_certificates(int argc, char * const *argv)
133 {
134 int ch, result = 0;
135 bool output_subject = false;
136 bool verbose = false;
137 bool trust_eval = false;
138 bool keychain_certs = false;
139 bool output_pem = false;
140 bool output_finger_print = false;
141 CFMutableArrayRef certs = NULL;
142 CFMutableDictionaryRef query = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
143
144 while ((ch = getopt(argc, argv, "kfq:pstv")) != -1)
145 {
146 switch (ch)
147 {
148 case 'k':
149 keychain_certs = true;
150 break;
151 case 'p':
152 output_pem = true;
153 break;
154 case 's':
155 output_subject = true;
156 break;
157 case 'v':
158 verbose = true;
159 break;
160 case 't':
161 trust_eval = true;
162 break;
163 case 'f':
164 output_finger_print = true;
165 break;
166 case 'q':
167 if (!keychain_query_parse_cstring(query, optarg)) {
168 CFReleaseNull(query);
169 return 1;
170 }
171 keychain_certs = true;
172 break;
173 case '?':
174 default:
175 return 2; /* @@@ Return 2 triggers usage message. */
176 }
177 }
178
179 argc -= optind;
180 argv += optind;
181
182 if ((keychain_certs && argc > 0) || (!keychain_certs && argc < 1))
183 result = 2;
184
185 if (trust_eval)
186 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
187
188 CFArrayRef kc_certs = NULL;
189 int arg;
190 if (keychain_certs) {
191 for (arg = 0; arg < argc; ++arg) {
192 if (!keychain_query_parse_cstring(query, argv[arg])) {
193 CFReleaseSafe(query);
194 CFReleaseSafe(certs);
195 return 1;
196 }
197 }
198 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
199 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
200 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
201 CFTypeRef results;
202 if (!SecItemCopyMatching(query, &results)) {
203 kc_certs = results;
204 argc = (int) CFArrayGetCount(kc_certs);
205 }
206 }
207
208 for (arg = 0; arg < argc; ++arg) {
209 SecCertificateRef cert = NULL;
210 if (keychain_certs) {
211 cert = (SecCertificateRef)CFArrayGetValueAtIndex(kc_certs, arg);
212 } else {
213 CFDataRef data = copyFileContents(argv[arg]);
214 if (data) {
215 cert = SecCertificateCreateWithData(
216 kCFAllocatorDefault, data);
217 if (!cert) {
218 /* DER failed, try PEM. */
219 cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data);
220 }
221 CFRelease(data);
222 } else {
223 result = 1;
224 }
225 }
226
227 if (cert) {
228 if (!keychain_certs) {
229 printf(
230 "*******************************************************\n"
231 "%s\n"
232 "*******************************************************\n"
233 , argv[arg]);
234 }
235 if (trust_eval) {
236 if (keychain_certs) {
237 CFArraySetValueAtIndex(certs, 0, cert);
238 show_cert_eval(certs, verbose);
239 } else {
240 CFArrayAppendValue(certs, cert);
241 }
242 } else {
243 if (verbose) {
244 print_cert(cert, verbose);
245 } else if (output_subject) {
246 CFStringRef subject = SecCertificateCopySubjectString(cert);
247 if (subject) {
248 CFStringWriteToFileWithNewline(subject, stdout);
249 CFRelease(subject);
250 }
251 } else if (!output_pem) {
252 print_cert(cert, verbose);
253 }
254 }
255 if (output_finger_print) {
256 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert);
257 if (key_fingerprint) {
258 int i;
259 CFIndex j = CFDataGetLength(key_fingerprint);
260 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint);
261
262 fprintf(stdout, "Key fingerprint:");
263 for (i = 0; i < j; i++) {
264 fprintf(stdout, " %02X", byte[i]);
265 }
266 fprintf(stdout, "\n");
267 }
268 CFReleaseSafe(key_fingerprint);
269 }
270 if (output_pem) {
271 print_buffer_pem(stdout, "CERTIFICATE",
272 SecCertificateGetLength(cert),
273 SecCertificateGetBytePtr(cert));
274 }
275 if (!keychain_certs) {
276 CFRelease(cert);
277 }
278 } else {
279 result = 1;
280 fprintf(stderr, "file %s: does not contain a valid certificate",
281 argv[arg]);
282 }
283 }
284
285 if (trust_eval && !keychain_certs)
286 show_cert_eval(certs, verbose);
287
288 CFReleaseSafe(kc_certs);
289 CFReleaseSafe(certs);
290
291 return result;
292 }
293
294 int trust_store_show_certificates(int argc, char * const *argv)
295 {
296 int ch, result = 0;
297 bool output_subject = false;
298 bool verbose = false;
299 bool trust_settings = false;
300 bool output_pem = false;
301 bool output_finger_print = false;
302 bool output_keyid = false;
303 CFArrayRef certs = NULL;
304
305 while ((ch = getopt(argc, argv, "fpstvk")) != -1)
306 {
307 switch (ch)
308 {
309 case 'p':
310 output_pem = true;
311 break;
312 case 's':
313 output_subject = true;
314 break;
315 case 'v':
316 verbose = true;
317 break;
318 case 't':
319 trust_settings = true;
320 break;
321 case 'f':
322 output_finger_print = true;
323 break;
324 case 'k':
325 output_keyid = true;
326 break;
327 case '?':
328 default:
329 return 2; /* @@@ Return 2 triggers usage message. */
330 }
331 }
332
333 if(SecTrustStoreCopyAll(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
334 &certs) || !certs) {
335 fprintf(stderr, "failed to get trust store contents for user\n");
336 return 1;
337 }
338
339 CFIndex ix, count = CFArrayGetCount(certs);
340 if (count) printf("*******************************************************\n");
341 for (ix = 0; ix < count; ix++) {
342 CFArrayRef certSettingsPair = NULL;
343 CFDataRef certData = NULL;
344 SecCertificateRef cert = NULL;
345
346 certSettingsPair = CFArrayGetValueAtIndex(certs, ix);
347 certData = (CFDataRef)CFArrayGetValueAtIndex(certSettingsPair, 0);
348 cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
349 if (!cert) {
350 fprintf(stderr, "failed to get cert at %ld\n",ix);
351 return 1;
352 }
353 if (verbose) {
354 print_cert(cert, verbose);
355 } else if (output_subject) {
356 CFStringRef subject = SecCertificateCopySubjectString(cert);
357 if (subject) {
358 CFStringWriteToFileWithNewline(subject, stdout);
359 CFRelease(subject);
360 }
361 } else if (output_pem) {
362 print_buffer_pem(stdout, "CERTIFICATE",
363 SecCertificateGetLength(cert),
364 SecCertificateGetBytePtr(cert));
365 } else {
366 print_cert(cert, verbose);
367 }
368 if (output_keyid) {
369 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert);
370 if (key_fingerprint) {
371 int i;
372 CFIndex j = CFDataGetLength(key_fingerprint);
373 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint);
374
375 fprintf(stdout, "Keyid:");
376 for (i = 0; i < j; i++) {
377 fprintf(stdout, " %02X", byte[i]);
378 }
379 fprintf(stdout, "\n");
380 }
381 CFReleaseSafe(key_fingerprint);
382 }
383 if (output_finger_print) {
384 CFDataRef fingerprint = SecCertificateGetSHA1Digest(cert);
385 if (fingerprint) {
386 int i;
387 CFIndex j = CFDataGetLength(fingerprint);
388 const uint8_t *byte = CFDataGetBytePtr(fingerprint);
389
390 fprintf(stdout, "Fingerprint:");
391 for (i = 0; i < j; i++) {
392 fprintf(stdout, " %02X", byte[i]);
393 }
394 fprintf(stdout, "\n");
395 }
396 }
397 if (trust_settings) {
398 CFPropertyListRef trust_settings = NULL;
399 trust_settings = CFArrayGetValueAtIndex(certSettingsPair, 1);
400 if (trust_settings && CFGetTypeID(trust_settings) != CFArrayGetTypeID()) {
401 fprintf(stderr, "failed to get trust settings for cert %ld\n", ix);
402 CFReleaseNull(cert);
403 return 1;
404 }
405 // place-holder until there are actual trust settings
406 CFStringRef settings = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), trust_settings);
407 char *settingsStr = NULL;
408 settingsStr = CFStringToCString(settings);
409 fprintf(stdout, "%s\n", settingsStr);
410 free(settingsStr);
411 CFRelease(settings);
412
413 }
414 printf("*******************************************************\n");
415 CFReleaseNull(cert);
416 }
417
418 CFRelease(certs);
419 return result;
420 }
421
422 #endif // TARGET_OS_EMBEDDED